2016-07-02 10 views
8

Tôi cố gắng tạo lớp có loại chung nơi tôi tạo hàm để đọc danh sách các thực thể. Và tôi biết rằng tôi có 2 cách để làm điều này: (# 1) bằng cách đọc từng thực thể trong một vòng lặp hoặc (# 2) tạo một bản đồ các thực thể trực tiếp."Loại không xác định gặp phải" khi sử dụng loại chung trong Firebase GenericTypeIndicator

cách thứ 2 trông hiệu quả hơn nhưng tiếc là GenericTypeIndicator không làm việc với loại generic - nó trả IllegalStateException: Unknown type encountered: T khi tôi sử dụng nó trong mã:

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

Vì vậy:

  1. Có cách nào để đọc loại thực thể chung trực tiếp vào bản đồ? (# 2)
  2. Hoặc chỉ là chúng không có sự khác biệt đáng kể về hiệu suất khi chỉ đọc các thực thể trong một vòng lặp (# 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) {} 
    }); 
} 

ví dụ: dữ liệu:

{ 
    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" 
     } 
    } 
} 

Trả lời

1

Sử dụng ParameterizedType để tìm một đối tượng lớp generic

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); 
Các vấn đề liên quan