2016-07-02 33 views
8

Provo a creare una classe con tipo generico dove creo la funzione per leggere l'elenco delle entità. E so che ho 2 modi per farlo: (# 1) leggendo ogni entità in un ciclo o (# 2) crea una mappa delle entità direttamente."Tipo sconosciuto rilevato" quando si utilizza il tipo generico in Firebase GenericTypeIndicator

secondo modo sembra più efficiente, ma purtroppo GenericTypeIndicator non funziona con tipo generico - restituisce IllegalStateException: Unknown type encountered: T quando lo uso in codice:

Map<String, T> entityMap = 
    dataSnapshot.getValue(new GenericTypeIndicator<Map<String, T>>() {}); 

Quindi:

  1. C'è un modo per leggi il tipo generico di entità direttamente in una mappa? (# 2)
  2. O semplicemente non hanno alcuna differenza significativa nelle prestazioni quando si legge solo le entità in un ciclo (n. 1)?
public class SomeClass<T extends KeyEntity> { 

    private final Class<T> mGenericClass; 
    private final String mRefKey; 

    public SomeClass(Class<T> clazz, String refKey) { 
     mGenericClass = clazz; 
     mRefKey = refKey; 
    } 

    public class KeyEntity { 
     private String mKey; 

     public KeyEntity() {} 

     public String getKey() { 
      return mKey; 
     } 

     public void setKey(String key) { 
      mKey = key; 
     } 
    } 

    public interface EntityListListener<T> { 
     abstract public void onEntityListLoaded(List<T> entity); 
    } 

    public void loadAll(final EntityListListener<T> entityListListener) { 
     DatabaseReference dbRef = FireDbUtils.getReference(mRefKey); 
     dbRef.addListenerForSingleValueEvent(new ValueEventListener() { 
      @Override 
      public void onDataChange(DataSnapshot dataSnapshot) { 
      List<T> entityList = new ArrayList<>((int) dataSnapshot.getChildrenCount()); 

      // #1 - read each entity in a loop 
      for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) { 
       T entity = dataSnapshot.getValue(mGenericClass); 
       entity.setKey(childSnapshot.getKey()); 
       entityList.add(entity); 
      } 

      // #2 - read all entity into a map 
      // GenericTypeIndicator doesn't like generic type 
      // if used, it returns "IllegalStateException: Unknown type encountered: T" 
      Map<String, T> entityMap 
       = dataSnapshot.getValue(new GenericTypeIndicator<Map<String, T>>() {}); 
      for (Map.Entry<String, T> pair : entityMap.entrySet()) { 
       T entity = pair.getValue(); 
       entity.setKey(pair.getKey()); 
       entityList.add(entity); 
      } 

      entityListListener.onEntityListLoaded(entityList); 
     } 

     @Override 
     public void onCancelled(DatabaseError databaseError) {} 
    }); 
} 

ad es. Dati:

{ 
    carList: { 
     carKey1: { 
      name: "wife car" 
     }, 
     carKey2: { 
      name: "my best car in the world ever" 
     } 
    }, 
    garageList: { 
     garageKey1: { 
      name: "house garage" 
     }, 
     garageKey2: { 
      name: "top secret garage under main garage" 
     } 
    } 
} 

risposta

1

Usa ParameterizedType per trovare un oggetto di classe generica

ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass(); 
//all generic classes  
Type[] args = type.getActualTypeArguments(); 

Class<T> genericClass = (Class<T>) args[0]; 

T entity = dataSnapshot.getValue(genericClass); 
Problemi correlati