para - guardar datos en firebase android
Al hacer un POJO en Firebase, ¿puedes usar ServerValue.TIMESTAMP? (6)
Cuando está creando un Objeto Java antiguo sin formato que debe ser serializado y deserializado a Firebase, ¿hay alguna manera de usar el valor
ServerValue.TIMESTAMP
?
Por ejemplo, supongamos que quiero tener un objeto donde una de las propiedades es la última vez que se editó y desea utilizar el valor
ServerValue.TIMESTAMP
.
En la clase POJO, podrías tener:
private String timeLastChanged;
o
private Map<String, String> timeLastChanged;
En el primer ejemplo con la
String
, me encuentro con el problema de establecer
timeLastChange = ServerValue.TIMESTAMP;
, porque
ServerValue.TIMESTAMP
es un mapa.
En el segundo ejemplo con el
Map<String, String>
recibo el error "no se pudo eliminar el rebote" porque no puede deserializar correctamente el tiempo almacenado en la base de datos en un
Map<String, String>
.
¿Hay alguna solución para esto?
El uso más común para Server.TIMESTAMP es:
- establecer el valor del servidor cuando los datos se ENVÍAN al servidor
- busca este modelo desde Firebase y envíalo fácilmente a Long
Este truco me ahorró el arduo trabajo de manejar 2 campos diferentes por solo 1 valor
public class HandleTimestampFirebaseObject {
Object timestamp;
public HandleTimestampFirebaseObject() {
}
public Object getTimestamp(){
if(timestamp instanceof Double){
/* this will handle the case of AFTER fetch from backend,and
serialize to object into SharedPreferences for example ,when the
Object casting automatically into Double.
(Anyway,call (long)getTimestamp from your code who use this model*/
return ((Double) timestamp).longValue();
}
else{
return timestamp; //this handle to firebase requirement in the server side(Object needed)
}
}
En lugar de usar @JsonIgnore, puedes usar Firebase native
@Exclude
.
Por ejemplo, trabajo en un proyecto similar y mi modelo es así.
package com.limte.app.borrador_1.mModel;
import com.google.firebase.database.Exclude;
import com.google.firebase.database.ServerValue;
/**
* Created by Familia on 20/12/2016.
*/
public class ChatItem {
String chatName;
Long creationDate;
public ChatItem() {
}
public String getChatName() {
return chatName;
}
public void setChatName(String chatName) {
this.chatName = chatName;
}
public java.util.Map<String, String> getCreationDate() {
return ServerValue.TIMESTAMP;
}
@Exclude
public Long getCreationDateLong() {
return creationDate;
}
public void setCreationDate(Long creationDate) {
this.creationDate = creationDate;
}
}
¡Y este código funciona! En Firebase, los resultados son: Results
Esa solución me parece un poco difícil ya que no sé qué está haciendo @JsonIgnore. Traté de hacerlo de una manera fácil y parece funcionar.
private Object dateLastChanged;
public Object getDateLastChanged() {
return dateLastChanged;
}
Para obtener algo legible para humanos, acabo de pasar el valor de retorno dateLastChanged Object en el siguiente método lanzándolo a Long.
static String convertTime(Long unixtime) {
Date dateObject = new Date(unixtime);
SimpleDateFormat dateFormatter = new SimpleDateFormat("dd-MM-yy hh:mmaa");
return dateFormatter.format(dateObject);
}
Bienvenido a las opiniones sobre mi solución ^^
La misma solución, pero yo uso esto.
@IgnoreExtraProperties
public class FIRPost {
Object timestamp;
public FIRPost() {
// Default constructor required for calls to DataSnapshot.getValue(FIRPost.class)
this.timestamp = ServerValue.TIMESTAMP;
}
public Object getTimestamp() {
return timestamp;
}
@Exclude
public Long getTimestamp(boolean isLong) {
if (timestamp instanceof Long) return (Long) timestamp;
else return null;
}
}
Quería mejorar un poco la respuesta de Lyla.
Primero, me gustaría deshacerme de los métodos
public HashMap<String, Object> getDateLastChanged() public HashMap<String, Object> getDateCreated()
.
Para hacerlo, puede marcar la propiedad
@JsonProperty
con la anotación
@JsonProperty
.
Otra forma posible de hacerlo es cambiar la detección de propiedades de esa manera:
@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
En segundo lugar, no entiendo por qué necesitamos poner
ServerValue.TIMESTAMP
en
HashMap
mientras que solo podemos almacenarlos como propiedad.
Entonces mi código final es:
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.firebase.client.ServerValue;
public class ShoppingList {
private String listName;
private String owner;
@JsonProperty
private Object created;
public ShoppingList() {
}
public ShoppingList(String listName, String owner) {
this.listName = listName;
this.owner = owner;
this.created = ServerValue.TIMESTAMP;
}
public String getListName() {
return listName;
}
public String getOwner() {
return owner;
}
@JsonIgnore
public Long getCreatedTimestamp() {
if (created instanceof Long) {
return (Long) created;
}
else {
return null;
}
}
@Override
public String toString() {
return listName + " by " + owner;
}
}
Actualización 27/12/2016
Cambió @JsonIgnore por @Exclude como muchos han mencionado.
Finalmente se me ocurrió una solución flexible para trabajar con Dates y ServerValue.TIMESTAMP. Esto está funcionando a partir de ejemplos de Ivan V , Ossama y puf .
No pude encontrar una manera de lidiar con la conversión entre
long
y
HashMap<String, String>
, pero si anida la propiedad en un
HashMap<String, Object>
más genérico
HashMap<String, Object>
puede ir a la base de datos como un solo largo valor ("fecha", "1443765561874") o como el mapa hash
ServerValue.TIMESTAMP
("fecha", {".sv", "tiempo de servicio"}).
Luego, cuando lo saque, siempre será un HashMap con ("fecha", "algún número largo").
Luego puede crear un método auxiliar en su clase POJO usando la anotación
@JsonIgnore
@Exclude (lo que significa que Firebase lo ignorará y no lo tratará como un método para serializar hacia / desde la base de datos) para obtener fácilmente el valor largo del HashMap devuelto a utilizar en su aplicación.
A continuación se muestra un ejemplo completo de una clase POJO:
import com.google.firebase.database.Exclude;
import com.firebase.client.ServerValue;
import java.util.HashMap;
import java.util.Map;
public class ExampleObject {
private String name;
private String owner;
private HashMap<String, Object> dateCreated;
private HashMap<String, Object> dateLastChanged;
/**
* Required public constructor
*/
public ExampleObject() {
}
public ExampleObject(String name, String owner, HashMap<String,Object> dateCreated) {
this.name = name;
this.owner = owner;
this.dateCreated = dateCreated;
//Date last changed will always be set to ServerValue.TIMESTAMP
HashMap<String, Object> dateLastChangedObj = new HashMap<String, Object>();
dateLastChangedObj.put("date", ServerValue.TIMESTAMP);
this.dateLastChanged = dateLastChangedObj;
}
public String getName() {
return name;
}
public String getOwner() {
return owner;
}
public HashMap<String, Object> getDateLastChanged() {
return dateLastChanged;
}
public HashMap<String, Object> getDateCreated() {
//If there is a dateCreated object already, then return that
if (dateCreated != null) {
return dateCreated;
}
//Otherwise make a new object set to ServerValue.TIMESTAMP
HashMap<String, Object> dateCreatedObj = new HashMap<String, Object>();
dateCreatedObj.put("date", ServerValue.TIMESTAMP);
return dateCreatedObj;
}
// Use the method described in https://.com/questions/25500138/android-chat-crashes-on-datasnapshot-getvalue-for-timestamp/25512747#25512747
// to get the long values from the date object.
@Exclude
public long getDateLastChangedLong() {
return (long)dateLastChanged.get("date");
}
@Exclude
public long getDateCreatedLong() {
return (long)dateCreated.get("date");
}
}