2015-11-17 24 views
7

Próbuję generalizować strukturę klasy.
Pokażę moją prawdziwą strukturę, aby była bardziej szczegółowa.W jaki sposób generować klasę za pomocą T i listy <T>

Piszę aplikacji w trybie offline, wsparcia, więc postanowiłem realizować moje ETag mechanizm cache w użyciu Robospice i GreenDao ORM.

Potrzebuję buforować tylko żądań GET.

pierwsze moje prośby należy rozszerzyć żądania bazową (nie moje), w moim przypadku RetrofitSpiceRequest<T, V>

T is type of return data 
V is service type, in my case I am using Retrofit. 

Problemem jest to, że typ zwracany jest nie List of T rodzaje domyślnie i trzeba utworzyć podklasę, która rozciąga tablicę T obiekty i używają go jako typu zwracającego.

coś takiego

public class City { 
.... 
.... 
.... 
    public static class List extends ArrayList<City> { 
    ..... 
    ..... 
    } 

} 

I używać City.List jako typ zwracany.

Ale mam mój DAO zadeklarowana następująco

public class CityDao extends AbstractDao<City, Long> { 

} 

Na każde żądanie (GET) muszę mieć konkretny DAO jako członka w celu buforowania danych, jeśli różni się on od danych serwera. Lub załaduj dane z lokalnej bazy danych, jeśli nie ma połączenia.

Problem polega na tym, że żądanie generowane przez typ T, który jest w większości listą, City.List w moim przypadku, niektórych obiektów, ale moje dao jest generowane przez, na przykład typ E, który jest miastem w moim przypadku.

Chcę utworzyć metodę tak

public AbastractDao<T,Long> getRequestDao() { 

} 

Ale jeśli chodzi o moją prośbę wraca City.List, nie mam pojęcia, jak generify tej klasy, czuję, że to jest możliwe, ale teraz nie ma pomysły .
W przypadku braku metody dao generycznego, muszę powielić kod jak ten

@Override 
    public void insertReceivedData(City.List received) { 
     mCityDao.insertOrReplaceInTx(received); 
    } 

@Override 
    public City.List getCachedData() { 
     if (mFilterMap != null && mFilterMap.size() > 0) { 
      return (City.List) mCityDao.loadAll(); 
     } else { 
      WhereCondition[] whereConditions = QueryUtils.convertPropertyMapToConditionalArray(mFilterMap); 
      return (City.List) mCityDao.queryBuilder().where(whereConditions[0], Arrays.copyOfRange(whereConditions, 1, whereConditions.length)).list(); 
     } 
    } 

W każdym żądaniu

Proszę podzielić się swoimi pomysłami.

Dzięki.

+0

Czy dobrze rozumiem to prawo, chcesz swoje usługi automatycznie wstrzyknąć i wywołać odpowiednią Dao? –

+0

Tak, ale problem polega na tym, że Dao jest rozszerzony AbstractDao i najczęściej używany jako AbstractDao gdzie T jest typem odwzorowanym na tabelę w moim przypadku miasta, ale muszę uzyskać listę miast, o ile żądanie zwraca obiekt klasa TI musi utworzyć niestandardową klasę MyCityList rozszerzającą ArrayList i tutaj jest problem. – CROSP

Odpowiedz

2

Kończę z następującym rozwiązaniem. Nie jest tak dobry, jak chciałem, ale działa lepiej niż duplikowanie kodu.

Moja podstawowa klasa żądania.

public abstract class BaseGetRequest<L extends List<T>, T, V> extends RetrofitSpiceRequest<L, V> implements FilterableRequest { 
    // Context 
    protected Context mContext; 
    // Filter used in request and in queries 
    protected Map<Property, String> mFilterMap; 
    // Session provided Singletone 
    protected DaoSessionProvider mSessionProvider; 

    public BaseGetRequest(Class<L> clazz, Class<V> retrofitedInterfaceClass, Context context, Map<Property, String> filterMap) { 
     super(clazz, retrofitedInterfaceClass); 
     mContext = context; 
     mFilterMap = filterMap; 
     mSessionProvider = ((DaoSessionProvider) mContext.getApplicationContext()); 
     // TODO determine required retry count 
     setRetryPolicy(new RetryPolicy() { 
      @Override 
      public int getRetryCount() { 
       return 0; 
      } 

      @Override 
      public void retry(SpiceException e) { 

      } 

      @Override 
      public long getDelayBeforeRetry() { 
       return 0; 
      } 
     }); 
    } 

    protected WhereCondition[] getWhereConditions() { 
     return QueryUtils.convertPropertyMapToConditionalArray(mFilterMap); 
    } 

    public BaseGetRequestV2(Class<L> clazz, Class<V> retrofitedInterfaceClass, Context context) { 
     this(clazz, retrofitedInterfaceClass, context, null); 
    } 

    public abstract AbstractDao<T, Long> getDao(); 

    public abstract L createDataList(List<T> list); 

    public L getCachedData() { 
     if (mFilterMap != null && mFilterMap.size() > 0) { 
      WhereCondition[] whereConditions = getWhereConditions(); 
      return createDataList(getDao().queryBuilder().where(whereConditions[0], Arrays.copyOfRange(whereConditions, 1, whereConditions.length)).list()); 
     } else { 
      return createDataList(getDao().loadAll()); 
     } 
    } 

    public abstract L getData(); 

    @Override 
    public Map<Property, String> getFilterMap() { 
     return mFilterMap; 
    } 

    public Map<String, String> getStringMap() { 
     return QueryUtils.convertPropertyMapToString(mFilterMap); 
    } 

    @Override 
    public L loadDataFromNetwork() throws Exception { 
     L receivedData = null; 
     try { 
      receivedData = getData(); 
      WhereCondition[] conditions = getWhereConditions(); 
      getDao().queryBuilder().where(conditions[0],Arrays.copyOfRange(conditions, 1, conditions.length)).buildDelete().executeDeleteWithoutDetachingEntities(); 
      getDao().insertOrReplaceInTx(receivedData); 
     } catch (Exception ex) { 
      receivedData = getCachedData(); 
     } 
     return receivedData; 
    } 
} 

I mogę przedłużyć tej klasy

public class NewsRequest rozciąga BaseGetRequest {public static final TARGET_URL String = "/ news"; NewsArticleDao mNewsArticleDao;

public NewsRequest(Context context) { 
    this(context, null); 
} 

public NewsRequest(Context context, Map<Property, String> filterMap) { 
    super(NewsArticle.List.class, API.class, context, filterMap); 
    mNewsArticleDao = mSessionProvider.getDaoSession().getNewsArticleDao(); 
} 

@Override 
public AbstractDao<NewsArticle, Long> getDao() { 
    return mNewsArticleDao; 
} 

@Override 
public NewsArticle.List createDataList(List<NewsArticle> list) { 
    return new NewsArticle.List(list); 
} 

@Override 
public NewsArticle.List getData() { 
    return getService().getNews(getStringMap()); 
} 

}

+0

Świetne rozwiązanie człowieka – ketazafor