I\'m using Retrofit to return rxjava Observable\'s for my async network calls.
I find myself repeating the following invocation:
someApiCall().subscrib
For Observable
responses, Retrofit currently sets the subscribeOn
as the HTTP executor of the RestAdapter
(either provided or the default). This was done to shim RxJava support into the existing behavior.
The plan for 2.0 is to provide the ability to set defaults for both subscribeOn
and observeOn
explicitly (whether it be both, only one, or neither).
A reason you wouldn't want always want observation on the main thread is if you needed to chain multiple API calls together, for example.
The Change Log of Retrofit Version 2.0.0-beta2 (2015-09-28) shows subscribeOn() is required for running in the background.
Fix: Observable and Single-based execution of requests now behave synchronously (and thus requires subscribeOn() for running in the background).
Yes, it's possible to remove both calls.
Here is the retrofit adapter class that automatically schedules both subscribeOn
and observedOn
to remove the need for the boilerplate calls in each invocation:
public class RxThreadingCallAdapterFactory extends CallAdapter.Factory {
private final RxJava2CallAdapterFactory original;
private RxThreadingCallAdapterFactory() {
// Always call on background thread
original = RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io());
}
public static CallAdapter.Factory create() {
return new RxThreadingCallAdapterFactory();
}
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
return new RxCallAdapterWrapper(original.get(returnType, annotations, retrofit));
}
private static class RxCallAdapterWrapper implements CallAdapter<Observable<?>> {
private final CallAdapter<?> wrapped;
public RxCallAdapterWrapper(CallAdapter<?> wrapped) {
this.wrapped = wrapped;
}
@Override
public Type responseType() {
return wrapped.responseType();
}
@Override
public <R> Observable<?> adapt(Call<R> call) {
Observable observable = (Observable) wrapped.adapt(call);
// Always handle result on main thread
return observable.observeOn(AndroidSchedulers.mainThread());
}
}
}
Then use this adapter when configuring retrofit:
Retrofit.Builder()
.baseUrl(...)
.addCallAdapterFactory(RxThreadingCallAdapterFactory.create())
I wrote this blog post that goes into a lot of detail on exactly what's happening here.
This will remove both calls, which I consider boilerplate. I consider Jake's scenario of chaining together background calls to not really apply, because in this case I would do retrofit synchronous calls and not use schedulers at all.
it is not the full answer to what you are looking for, but this at least removes the burden of righting subscribeOn(Schedulers.io())
retrofit = new Retrofit
.Builder()
.baseUrl(app.getUrlBase())
.client(httpClient)
.addCallAdapterFactory(
RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()) // <-- default subscribeOn()
)
.addConverterFactory(jsonFactory)
.build();