2016-07-08 39 views
6

Desidero utilizzare auto-value con firebase 9.2.0+. Ho il seguente codice:Come utilizzare il valore automatico con firebase 9.2 in Android

@AutoValue 
public abstract class Office { 

    public static Builder builder() { 
     return new AutoValue_Office.Builder(); 
    } 

    public abstract double latitud(); 
    public abstract double longitud(); 

    @AutoValue.Builder 
    public static abstract class Builder { 

     public abstract Builder latitud(double latitud); 
     public abstract Builder longitud(double longitud); 

     public abstract Office build(); 

    } 

} 

Ma quando faccio chiamare questo Office office = childDataSnapshot.getValue(Office.class); sto ottenendo questo errore:

com.google.firebase.database.DatabaseException: No properties to serialize found on class com.example.app.model.Office 

Qualcuno ha un'idea perché sto ottenendo questo errore e come risolverlo? Ho letto che Firebase non utilizza più la serializzazione json jackson. Quindi non sono sicuro di come specificare un tipo di @JsonProperty("latitud") che ho usato @PropertyName senza successo.

Ho provato anche rinominare i metodi astratti come public abstract double getLatitud(); e dopo che l'errore è il prossimo:

java.lang.InstantiationException: Can't instantiate abstract class com.example.app.model.Office 

quindi non sono sicuro di come risolvere questo.

SOLUZIONE

Grazie alla hatboysam e Frank van Puffelen ho finalmente potuto affrontare questo problema con la soluzione successiva.

  1. Ho creato un FirebaseUtil enum con due metodi per serializzare e deserializzare oggetti per Firebase basate su hatboysam risposta e Frank van Puffelen commento.
  2. Creo un paio di classi User e Phone per il test.
  3. Dipendenze: esempio

    compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.0' 
    compile 'com.fasterxml.jackson.core:jackson-databind:2.8.0' 
    
  4. Usage:

    User user = FirebaseUtil.deserialize(dataSnapshot, User.class); 
    Map<String, Object> map = FirebaseUtil.serialize(user); 
    
+0

Una domanda: qual è lo scopo che sta dietro all'uso Auto-valore? Per rendere Parcelable? –

risposta

4

io non sono sicuro che questo è possibile con i dati Firebase mapper di default, ma c'è una soluzione possibile. Prima di tutto spiegare gli errori che stai vedendo:

com.google.firebase.database.DatabaseException: No properties to serialize found on class com.example.app.model.Office

Il mapper Firebase sembra sia per public campi o campi denominati con il modello getFoo/setFoo. Quindi sulla tua classe il mapper non vede alcuna proprietà.

java.lang.InstantiationException: Can't instantiate abstract class com.example.app.model.Office

Questo è quello che penso avrai problemi a spostarti. Affinché la deserializzazione funzioni, la tua classe deve avere un costruttore pubblico, senza argomenti, che il mappatore può chiamare tramite riflessione (newInstance()). Per quanto ne so, non è così che funziona AutoValue.

Ma non perdere la speranza!. Secondo this github issue c'è un modo per rendere compatibili Jackson e AutoValue usando l'annotazione @JsonCreator. Quindi avrai bisogno di usare Jackson e Firebase per completare il lavoro qui.

Serializzare:

// Convert to a Map<String,Object> using Jackson and then pass that to Firebase 
ObjectMapper mapper = new ObjectMapper(); 
Map<String, Object> map = mapper.convertValue(office, Map.class); 
databaseReference.setValue(map); 

deserializzazione:

// Use Firebase to convert to a Map<String,Object> 
GenericTypeIndicator<Map<String,Object>> t = new GenericTypeIndicator<Map<String,Object>>() {}; 
Map<String,Object> map = dataSnap.getValue(t); 

// Use Jackson to convert from a Map to an Office object 
ObjectMapper mapper = new ObjectMapper(); 
Office pojo = mapper.convertValue(map, Office.class); 
+0

Sì, scusate ho dimenticato di dire che ho provato a risolvere il problema senza successo, come ho potuto leggere/ricerca Firebase non usa più Jackson. Quindi questo lavoro non ha funzionato per me:/ – epool

+0

@epool che cosa esattamente su questa soluzione alternativa non funziona per te? Mentre Firebase non usa più Jackson internamente, puoi comunque usare Jackson come compagno di Firebase. –

+0

Per informazioni su come utilizzare Jackson con gli ultimi SDK di Firebase, vedere http://stackoverflow.com/questions/37547399/how-to-deserialise-a-subclass-in-firebase-using-getvaluesubclass-class/37548330#37548330 –

0

ho scritto un AutoValue estensione per questo:

https://github.com/mattlogan/auto-value-firebase

L'estensione genera una classe compatibile Firebase, chiamato FirebaseValue, come classe interna statica nella classe AutoValue generata. È possibile convertire tra la classe AutoValue e la classe FirebaseValue tramite i costruttori generati.

Ecco un esempio, copiato dal readme, di quello che sembra:

@AutoValue @FirebaseValue 
public abstract class Taco { 

    public static Taco create(String name, List<Ingredient> ingredients, Review review) { 
    return new AutoValue_Taco(name, ingredients, review); 
    } 

    // Create AutoValue_Taco instance from AutoValue_Taco.FirebaseValue instance 
    public static Taco create(DataSnapshot dataSnapshot) { 
    AutoValue_Taco.FirebaseValue taco = dataSnapshot.getValue(AutoValue_Taco.FirebaseValue.class); 
    return new AutoValue_Taco(taco); 
    } 

    // Create AutoValue_Taco.FirebaseValue instance from AutoValue_Taco instance 
    public Object toFirebaseValue() { 
    return new AutoValue_Taco.FirebaseValue(this); 
    } 

    public abstract String name(); 

    public abstract List<Ingredient> ingredients(); 

    public abstract Review review(); 
} 
+1

Bello! suona molto bene! Daro un'occhiata a questo fine settimana, buon lavoro! :) – epool