android firebase timestamp firebase-realtime-database

android - ¿Cómo usar la marca de tiempo del servidor Firebase para generar la fecha de creación?



timestamp firebase-realtime-database (2)

Actualmente, la versión de Google de ServerValue.TIMESTAMP devuelve {".sv":"timestamp"} que se utiliza como directiva para que Firebase complete ese campo con la marca de tiempo del servidor una vez que guarde los datos en el servidor de Firebase.

Sin embargo, cuando crea sus datos en el lado del cliente, todavía no tiene la marca de tiempo real para jugar (es decir, usar como fecha de creación). Solo tendrá acceso a la marca de tiempo después del guardado inicial y la recuperación posterior, que, imagino, a veces es demasiado tarde y no muy elegante.

Antes de google:

Actualización: ignore esta sección porque es incorrecta. No entendí bien los ejemplos. ServerValue.TIMESTAMP siempre devolvió el {".sv":"timestamp"} .

Según tengo entendido en Firebase anterior a Google, parecía haber una marca de tiempo generada por el servidor disponible que le permitía adquirir la marca de tiempo real:

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

( ref 1 , ref 2 )

Preguntas:

  1. ¿Es este guardado / recuperación la única forma de obtener la fecha de creación generada por el servidor en mis instancias de modelo?
  2. En caso afirmativo, ¿puede proponer un método para implementar dicho patrón?
  3. ¿Estoy entendiendo correctamente ServerValue.TIMESTAMP ha cambiado con la adquisición de Firebase por parte de Google? Actualización: No, @FrankvanPuffelen respondió que nada ha cambiado durante la adquisición.

Nota:

No estoy considerando usar la new Date() en el lado del cliente, ya que he estado leyendo que no es seguro, aunque por favor comparta sus pensamientos si piensa diferente.


Cuando usas la constante ServerValue.TIMESTAMP en una operación de escritura, estás diciendo que el servidor de Firebase Database debe determinar la marca de tiempo correcta cuando ejecuta la operación de escritura.

Digamos que ejecutamos este código:

ref.addValueEventListener(new ValueEventListener() { public void onDataChange(DataSnapshot dataSnapshot) { System.out.println(dataSnapshot.getValue()); } public void onCancelled(DatabaseError databaseError) { } }); ref.setValue(ServerValue.TIMESTAMP);

Esto se ejecutará de la siguiente manera:

  1. adjuntas un oyente
  2. escribe un valor con ServerValue.TIMESTAMP
  3. el cliente Firebase dispara inmediatamente un evento de valor con una aproximación de la marca de tiempo que escribirá en el servidor
  4. su código imprime ese valor
  5. la operación de escritura se envía a los servidores de Firebase
  6. los servidores de Firebase determinan la marca de tiempo real y escriben el valor en la base de datos (suponiendo que no fallan las reglas de seguridad)
  7. el servidor Firebase envía la marca de tiempo real de vuelta al cliente
  8. el cliente de Firebase genera un evento de valor para el valor real
  9. su código imprime ese valor

Si está utilizando ChildEventListener lugar de ValueEventListener , entonces el cliente llamará a onChildAdded en el paso 3 y onChildChanged en el paso 8.

Nada cambió en la forma en que generamos ServerValue.TIMESTAMP desde que Firebase se unió a Google. El código que funcionó antes, seguirá funcionando. Eso también significa que la primera respuesta que vinculó es una forma válida de manejarla.


Lo estoy haciendo un poco diferente.

Solución 1: método push() en POJO

Como no quiero saturar mis POJO con extractores o propiedades extrañas, solo estoy definiendo un método push() dentro de mis POJO que se ve así:

/** * 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(this@Pojo) child(Pojo.CREATED_AT_KEY).setValue(ServerValue.TIMESTAMP) } }

Luego, simplemente puedo crear una instancia del POJO y llamar a push() que llena correctamente la propiedad de tiempo de creación.

Esto definitivamente hace que el POJO sea un poco menos claro e implica una lógica que un POJO no debería conocer. Sin embargo, usar @Exclude anotaciones y / o @Exclude como se describe en algunas de las respuestas here también requiere conocimiento del mecanismo de almacenamiento.

Solución 2: extensión de referencia de DatabaseReference o ayudante (Kotlin)

Para superar esto, por supuesto, también puede crear un pushTask(task: Task) en un asistente o, si usa Kotlin, un método de extensión para, por ejemplo, DatabaseReference que podría verse así:

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

Al mirarlo ahora, llego a pensar que en realidad me gusta más el segundo enfoque ( si tengo a Kotlin a mi disposición, no me gustan los ayudantes). Pero esto es probablemente solo una cuestión de gustos. ;)