2017-04-22 23 views
1

繼討論here的主題後。我正在使用Clean Architecture編寫Android應用程序。我有一個Interactor負責回顧用戶的Feed數據。流程如下:管理來自不同rx.Observables的不同異常

  • 我必須從調用Retrofit的服務來執行API調用的Repository中獲取Feed數據。
  • 如果出現問題,我必須從內部使用Sqlite的FeedCache中提取Feed數據。
  • 我必須將此供稿集合與另一個名爲PendingPostCache的緩存中的另一批供稿合併。此緩存包含用戶無法發佈的所有文章(因爲出錯,沒有連接互聯網等)

我的FeedCache和PendingPostCache都與Sqlite一起使用。如果出現問題,Botch可以拋出DBException。如果出現錯誤(ServerSideException),我的FeedRepository使得對服務器端的請求可能會引發異常。

下面是從我的交互器整個代碼:

mFeedRepository.getFeed(offset, pageSize) //Get items from the server-side 
       .onErrorResumeNext(mFeedCache.getFeed(userSipid)) //If something goes wrong take it from cache 
       .mergeWith(mPendingPostCache.getAllPendingPostsAsFeedItems(user)) //Merge the response with the pending posts 
       .subscribe(new DefaultSubscriber<List<BaseFeedItem>>() { 
        @Override 
        public void onNext(List<BaseFeedItem> baseFeedItems) { 
         callback.onFeedFetched(baseFeedItems); 
        } 

        @Override 
        public void onError(Throwable e) { 
         if (e instanceof ServerSideException) { 
          //Handle the http error 
         } else if (e instanceof DBException) { 
          //Handle the database cache error 
         } else { 
          //Handle generic error 
         } 
        } 
       }); 

我不喜歡這些的instanceof。我正在考慮創建一個自定義訂閱者,這個名爲MyAppSubscriber的東西,它實現了onError方法,進行這些instanceof比較,並執行一些名爲onServerError()的方法,onDBError()。這樣代碼將變得更加清潔,並且我可以不用編寫這個樣板代碼。有人對如何解決這個問題有更好的想法嗎?一些方法來避免自定義用戶?

回答

3

只需使用組成:

public <T,E> Function<Throwable, Observable<T>> whenExceptionIs(Class<E> what, Function<E, Observable<T>> handler) { 
    return t -> { 
    return what.isInstance(t) ? handler.apply(what.cast(t)) : Observable.error(t); 
    }; 
} 

然後你使用它正常:

Observable.from(...).flatMap(...) 
.onErrorResumeNext(whenExceptionIs(ServerSideException.class, e-> Observable.empty())) 
.onErrorResumeNext(whenExceptionIs(DBException.class, e-> ...)) 

你甚至可以抽象的一切,在一個方法:

public <T> Transformer<T, T> errorHandling() { 
    return src -> src 
     .onErrorResumeNext(whenExceptionIs(ServerSideException.class, e-> Observable.empty())) 
     .onErrorResumeNext(whenExceptionIs(DBException.class, e-> ...)); 
} 


Observable.from(...).flatMap(...) 
.compose(errorHandling()) 
.subscribe();