2016-06-16 28 views
11

Attualmente, la versione di Google di ServerValue.TIMESTAMP restituisce {".sv":"timestamp"} che viene utilizzata come una direttiva per Firebase per riempire quel campo con il timestamp del server una volta salvati i dati sul server Firebase.Come utilizzare il timestamp del server Firebase per generare la data di creazione?

Quando si creano i dati sul lato client, tuttavia, non si ha ancora il timestamp effettivo con cui giocare (ad esempio, utilizzare come data di creazione). Avrai solo accesso al timestamp dopo il salvataggio iniziale e il conseguente recupero, che - immagino - a volte è troppo tardi e non molto elegante.


Prima di Google:

Update: Ignorare questa sezione in quanto non è corretta - ho capito male gli esempi. ServerValue.TIMESTAMP restituiva sempre il {".sv":"timestamp"}.

Per quanto ho capito in pre-google Firebase ci sembrava di essere un timestamp generato dal server disponibili che vi ha permesso di acquisire il timestamp attuale:

import com.firebase.client.ServerValue; 
ServerValue.TIMESTAMP // eg. 1466094046 

(ref 1, ref 2)


Domande:

  1. Tale salvataggio/recupero è l'unico modo per ottenere la data di creazione generata dal server nelle istanze del modello?
  2. Se sì, puoi proporre un metodo per implementare tale modello?
  3. Sto comprendendo correttamente ServerValue.TIMESTAMP è cambiato con l'acquisizione di Firebase da parte di Google? Aggiornamento : No, @FrankvanPuffelen ha risposto che nulla è cambiato durante l'acquisizione.

Nota:

non sto pensando di utilizzare new Date() sul lato client, come ho letto non è sicuro, anche se si prega di condividere i tuoi pensieri se si pensa diverso.

+0

* firebaser qui * Nulla è cambiato nel modo in cui generiamo il 'ServerValue.TIMESTAMP' da quando siamo entrati in Google. Codice che ha funzionato prima, continuerà a funzionare. Se hai codice che non funziona, aggiungi il codice minimale che riproduce il problema nella tua domanda per favore. –

+0

@FrankvanPuffelen Ho frainteso i vecchi esempi, grazie. 'ServerValue.TIMESTAMP' ha sempre restituito' {".sv": "timestamp"} '. Non mi riferisco al codice che non funziona, ma solo una domanda teorica su come utilizzare correttamente il timestamp del server per lavorare con * data di creazione * – Voy

risposta

20

Quando si utilizza la costante ServerValue.TIMESTAMP in un'operazione di scrittura, si sta dicendo che il server del database Firebase dovrebbe determinare il timestamp corretto quando esegue l'operazione di scrittura.

Diciamo che corriamo questo codice:

ref.addValueEventListener(new ValueEventListener() { 
    public void onDataChange(DataSnapshot dataSnapshot) { 
     System.out.println(dataSnapshot.getValue()); 
    } 

    public void onCancelled(DatabaseError databaseError) { } 
}); 
ref.setValue(ServerValue.TIMESTAMP); 

Questo eseguirà come segue:

  1. si allega un ascoltatore
  2. si scrive un valore con ServerValue.TIMESTAMP
  3. il cliente Firebase immediato attiva un evento di valore con un'approssimazione del timestamp che scriverà sul server
  4. le stampe di codice che valore
  5. l'operazione di scrittura viene inviato ai server di Firebase
  6. i server Firebase determinano il timestamp reale e scrivere il valore nel database (assumendo regole di sicurezza non riescono)
  7. server Firebase inviare il attuale timestamp al client
  8. il cliente Firebase genera un evento valore per il valore effettivo
  9. le stampe di codice che apprezzano

Se stai usando ChildEventListener invece di un ValueEventListener, allora il cliente chiamerà onChildAdded al punto 3 e onChildChanged al punto 8.

Nulla cambiato nel modo in cui generiamo il ServerValue.TIMESTAMP dal Firebase unito a Google. Codice che ha funzionato prima, continuerà a funzionare. Ciò significa anche che lo first answer you linked è un modo valido per gestirlo.

0

Lo sto facendo un po 'diversamente.

Soluzione 1: push() metodo POJO

Come io non voglio ingombrare i miei POJO con strane getter o proprietà, sto solo definendo un metodo push() dentro le mie POJO che assomiglia a questo:

/** 
* Pushes a new instance to the DB. 
* 
* @param parentNode `DatabaseReference` to the parent node this object shall be attached to 
*/ 
fun push(parentNode: DatabaseReference) { 
    parentNode 
     .push() 
     .apply { 
      setValue([email protected]) 
      child(Pojo.CREATED_AT_KEY).setValue(ServerValue.TIMESTAMP) 
     } 
} 

allora posso semplicemente creare un'istanza della POJO e chiamare push() su di esso che popola correttamente la proprietà ora di creazione.

Ciò rende il POJO un po 'meno semplice e implica una logica che un POJO non dovrebbe conoscere. Tuttavia, l'utilizzo delle annotazioni e/o cast @Exclude come indicato in alcune delle risposte here richiede anche la conoscenza del meccanismo di memorizzazione.

Soluzione 2: Helper o DatabaseReference estensione (Kotlin)

Per superare questo si può ovviamente anche solo creare un metodo pushTask(task: Task) in un aiutante o - se si utilizza Kotlin - un metodo di estensione per esempioDatabaseReference che potrebbe assomigliare a questo:

fun DatabaseReference.push(pojo: Pojo) { 
    push() 
    .apply { 
     setValue(pojo) 
     child(Pojo.CREATED_AT_KEY).setValue(ServerValue.TIMESTAMP) 
    } 
} 

Guardando ora io vengo a pensare che io in realtà come il secondo approccio più (se devo Kotlin a mia disposizione - non mi piace aiutanti). Ma questa è probabilmente solo una questione di gusti. ;)