2016-07-08 22 views
6

Chcę użyć auto-value z firebase 9.2.0+. Mam następujący kod:Jak używać auto-value z firebase 9.2 w Androidzie

@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(); 

    } 

} 

Ale kiedy zrobić, aby wywołać tę Office office = childDataSnapshot.getValue(Office.class); otrzymuję ten błąd:

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

ktoś ma pomysł dlaczego ja otrzymuję ten błąd i jak go rozwiązać? Czytałem, że baza ogniowa nie używa już do serializacji json. Więc nie jestem pewien, jak określić rodzaj @JsonProperty("latitud") Użyłem @PropertyName bez powodzenia.

Próbowałem również zmienić nazwę metody abstrakcyjne jak public abstract double getLatitud(); i po, że błąd jest następny:

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

więc nie jestem pewien, jak rozwiązać ten problem.

ROZWIĄZANIE

Dzięki hatboysam i Frank van Puffelen I wreszcie mogli zmierzyć się z tym problemem do następnego rozwiązania.

  1. stworzyłem FirebaseUtil enum z dwóch metod serializacji i odserializacji obiektów do Firebase podstawie hatboysam odpowiedź i Frank van Puffelen komentarza.
  2. Tworzę kilka klas User i Phone do testowania.
  3. Zależności: Przykład

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

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

jedno pytanie: jaki jest cel za użyciem Auto-wartość? Za wykonanie Parcelable? –

Odpowiedz

4

nie jestem pewien, że to jest możliwe z domyślnym Firebase danych odwzorowującym, ale nie jest możliwe obejście. Po pierwsze wyjaśnijmy błędów jesteś zobaczyć:

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

Firebase odwzorowujący wygląda zarówno dla public pola lub pól nazwanych wzorkiem getFoo/setFoo. Tak więc w twojej klasie mapper nie widzi żadnych właściwości.

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

To jest ten, który myślę, że będziesz miał kłopoty z poruszaniem się. Aby deserializacja działała, twoja klasa musi mieć publiczny, nieargumentowany konstruktor, który program odwzorowujący może wywoływać poprzez odbicie (newInstance()). O ile wiem, nie jest tak, jak działa AutoValue.

Ale nie trać nadziei!. Według this github issue istnieje sposób na dostosowanie Jackson i AutoValue przy użyciu adnotacji @JsonCreator. Musisz więc użyć zarówno Jackson, jak i Firebase, aby wykonać zadanie tutaj.

szeregowania:

// 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); 

deserializacji:

// 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

Tak, przepraszam, zapomniałem wspomnieć, że próbowałem tego obejścia bezskutecznie, ponieważ mogłem czytać/badać, że baza ogniowa już nie używa Jacksona. Więc ta praca nie działa dla mnie:/ – epool

+0

@pool, co dokładnie o tym obejściu nie działa dla ciebie? Podczas gdy Firebase nie używa już wewnętrznie Jacksona, możesz nadal używać Jacksona jako towarzysza do bazy ogniowej. –

+0

Aby dowiedzieć się, jak korzystać z Jacksona z najnowszymi pakietami SDK Firebase, zobacz http://stackoverflow.com/questions/37547399/how-to-deserialise-a-subclass-in-firebase-using-getvaluesubclass-class/37548330#37548330 –

0

napisałem AutoValue rozszerzenia dla tego:

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

Rozszerzenie generuje Firebase zgodną klasę, zwany FirebaseValue, jako statyczna klasa wewnętrzna w wygenerowanej klasie AutoValue. Możesz konwertować pomiędzy klasą AutoValue i klasą FirebaseValue za pośrednictwem wygenerowanych konstruktorów.

Oto przykład, skopiowany z readme, co wygląda na to, że:

@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

Nice! brzmi bardzo dobrze! Popatrzę w ten weekend na mężczyznę, dobra robota! :) – epool