2014-06-26 5 views
6

Sto esplorando RxJava e la sua applicabilità ad Android, e sto cercando di implementare un semplice caso d'uso con cache di caricamento, come mostrato sul seguente ASCII grafico:RxJava Android - Carica-cache-mostra i dati sui thread appropriati

    --------------- 
     --- failure --| Load data |-- success --- 
     |    ---------------    | 
     V           V 
-------------------      ------------- 
| Get from cache |      | Filter | 
-------------------      ------------- 
     |           | 
     |           V 
     |   ----------------  ------------- 
     ------------>| Display |<------| Cache | 
        ----------------  ------------- 

Ecco il codice che ho inizialmente si avvicinò con:

subscription = AndroidObservable.bindFragment(this, restClient.getItems()) 
       .onErrorReturn(new Func1<Throwable, List<Item>>() { 
        @Override public List<Item> call(Throwable throwable) { 
         return itemsDao.getCachedItems(); 
        } 
       }) 
       .flatMap(new Func1<ItemContainer, Observable<Item>>() { 
        @Override public Observable<Item> call(ItemContainer itemContainer) { 
         return Observable.from(itemContainer.getItems()); 
        } 
       }) 
       .filter(new Func1<Item, Boolean>() { 
        @Override public Boolean call(Item item) { 
         return item.getName().startsWith("B"); 
        } 
       }) 
       .toList() 
       .map(new Func1<List<Item>, List<Item>>() { 
        @Override public List<Item> call(List<Item> items) { 
         itemsDao.cacheItems(items); 
         return items; 
        } 
       }) 
       .subscribeOn(Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR)) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(new Action1<List<Item>>() { 
        @Override public void call(List<Item> items) { 
         displayData(items); 
        } 
       }); 

Come previsto, il networking e la memorizzazione nella cache vengono eseguiti su un thread in background, e la visualizzazione dei dati avviene su thread dell'interfaccia utente. Il problema è che i dati restituiti da onErrorReturn() passano attraverso lo stesso ciclo di filtraggio e memorizzazione nella cache, che è ridondante. Tuttavia, se cambio il codice a questo:

subscription = AndroidObservable.bindFragment(this, restClient.getItems()) 
        .flatMap(new Func1<ItemContainer, Observable<Item>>() { 
         @Override public Observable<Item> call(ItemContainer itemContainer) { 
          return Observable.from(itemContainer.getItems()); 
         } 
        }) 
        .filter(new Func1<Item, Boolean>() { 
         @Override public Boolean call(Item item) { 
          return item.getName().startsWith("B"); 
         } 
        }) 
        .toList() 
        .map(new Func1<List<Item>, List<Item>>() { 
         @Override public List<Item> call(List<Item> items) { 
          itemsDao.cacheItems(items); 
          return items; 
         } 
        }) 
        .onErrorReturn(new Func1<Throwable, List<Item>>() { 
         @Override public List<Item> call(Throwable throwable) { 
          return itemsDao.getCachedItems(); 
         } 
        }) 
        .subscribeOn(Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR)) 
        .observeOn(AndroidSchedulers.mainThread()) 
        .subscribe(new Action1<List<Item>>() { 
         @Override public void call(List<Item> items) { 
          displayData(items); 
         } 
        }); 

displayData() non viene mai chiamato. Quale sarebbe il modo giusto di comporre questi osservabili per attuare lo schema che ho?

risposta

5

Risolto sostituendo onErrorReturn() chiamata con onErrorResumeNext(Observable.just(itemsDao.getCachedItems()))