I have been using MVP
architecture with Retrofit
with callbacks
for some time. I would like to replace my callbacks with RxJava/Android
but I can't seem to grasp on how it should be done.
I have an interface for the Interceptor(Interactor):
public interface FoodInterceptor extends MvpInterceptor {
/*void getFoodList(RestCallback<FoodListResponse> callback);*/
Observable getFoodList(Consumer<FoodListResponse> foodListResponseConsumer, Consumer<Throwable> error);
}
And then the interceptor implementation:
public class FoodInterceptorImpl implements FoodInterceptor {
@Inject
ApiService mApiService;
@Inject
ErrorUtils mErrorUtils;
@Inject
SchedulerProvider mSchedulerProvider;
@Inject
CompositeDisposable mCompositeDisposable;
@Inject
public FoodInterceptorImpl() {
super();
}
@Override
public Observable<FoodListResponse> getFoodList(Consumer<FoodListResponse> foodListResponseConsumer, Consumer<Throwable> throwable) {
mApiService.getFoodList()
.subscribeOn(mSchedulerProvider.backgroundThread())
.observeOn(mSchedulerProvider.mainThread())
.subscribe(foodListResponse -> Log.d("TAG", "FoodResponse: " + foodListResponse),
throwable1 -> Log.d("TAG", "Throwable: " + throwable));
return ?;
}
@Override
public void unbind() {
}
/*@Override
public void getFoodList(final RestCallback<FoodListResponse> callback) {
mApiService.getFoodList().enqueue(new Callback<FoodListResponse>() {
@Override
public void onResponse(Call<FoodListResponse> call, Response<FoodListResponse> response) {
if (response.isSuccessful()) {
Result<FoodListResponse> result = new Result<>();
FoodListResponse foodListResponse = response.body();
result.setData(foodListResponse);
callback.onSuccess(result);
} else {
mRestError = mErrorUtils.parseResponse(response);
Log.d("Test", "Error: " + mRestError.getMessage());
}
}
@Override
public void onFailure(Call<FoodListResponse> call, Throwable t) {
}
});
}*/
/*@Override
public void cleanup() {
}*/
}
In the commented code you can see how I would do it with a callback, but Rx required me to return Observable
. How would I do that? And how do I inform my presenter that data has been fetched?
Presenter interface:
@PerActivity
public interface FoodPresenter<V extends FoodView, I extends FoodInterceptor> extends MvpPresenter<V, I> {
void renderFoods();
}
And the Presenter:
public class FoodPresenterImpl<V extends FoodView, I extends FoodInterceptor>
extends BasePresenter<V, I> implements FoodPresenter<V, I> {
@Inject
public FoodPresenterImpl(I mvpInterceptor,
SchedulerProvider schedulerProvider,
CompositeDisposable compositeDisposable) {
super(mvpInterceptor, schedulerProvider, compositeDisposable);
}
@Override
public void renderFoods() {
getMvpView().showProgress(true);
getInterceptor().getFoodList(foodListResponse -> {
if (!isViewAttached()) {
return;
}
getMvpView().renderFoods(foodListResponse.getFoodList().getFoodItemList());
getMvpView().showProgress(false);
}, throwable -> {
if (!isViewAttached()) {
return;
}
getMvpView().showProgress(false);
});
}
/*@Override
public void renderFoods() {
getMvpView().showProgress(true);
getInterceptor().getFoodList(new RestCallback<FoodListResponse>() {
@Override
public void onSuccess(Result<FoodListResponse> result) {
if (!isViewAttached()) {
return;
}
getMvpView().renderFoods(result.getData().getFoodList().getFoodItemList());
getMvpView().showProgress(false);
}
@Override
public void onFailure(RestError error) {
}
});
}*/
}
Let me decompose you logic a bit:
renderFoods
get called in presenterInterceptor call mApi.getFoodList()
(it should return Observable
) and itnterceptro subscribes to result. I will use lambda, so there can be missed parts:
mApi.getFoodList()
.subscribeOn(Schedulers.io()) // main work will be on io thread
.observeOn(AndroidSchedulers.mainThread()) // result will be passed to main thread
.subscribe((result, throwable) -> {
// it's like your calback, the job are done
// and you get result in result parameter,
// and if error occurs, result will be null
// and throwable parameter has an cause
// so, here you can apply errorUtils on result, check the throwable,
// or pass result to your presenter
});
Hope it helps!