Reputation: 4073
Following the topic discussed here. I'm coding an Android App using the Clean Architecture. I've an Interactor that takes care of retriving the User's feed data. The flow is like this:
My FeedCache and PendingPostCache both work with Sqlite. Botch can throw DBExceptions if something went wrong. My FeedRepository the ones that makes the requests against the server-side can also throw exceptions if something goes wrong (ServerSideException).
Here's the whole code from my Interactor:
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
}
}
});
I don't like having those instanceof. I'm thinking on creating a custom subscriber, something called like MyAppSubscriber, which implements the onError method, makes those instanceof comparations, and execute some methods called onServerSideError(), onDBError(). That way the code is going te be a lot cleaner and I can spare writing that instanceof boilerplate code. Has someone a better idea about how to approach this issue? Some way to avoid the custom Subscriber?
Upvotes: 1
Views: 97
Reputation: 16142
Just use composition:
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);
};
}
Then you use it normally :
Observable.from(...).flatMap(...)
.onErrorResumeNext(whenExceptionIs(ServerSideException.class, e-> Observable.empty()))
.onErrorResumeNext(whenExceptionIs(DBException.class, e-> ...))
You can even abstract all that in one method:
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();
Upvotes: 3