Default Schedulers for rxjava on Android

前端 未结 4 497
予麋鹿
予麋鹿 2021-01-01 20:32

I\'m using Retrofit to return rxjava Observable\'s for my async network calls.

I find myself repeating the following invocation:

someApiCall().subscrib

相关标签:
4条回答
  • 2021-01-01 20:55

    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.

    0 讨论(0)
  • 2021-01-01 20:56

    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).

    0 讨论(0)
  • 2021-01-01 21:06

    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.

    0 讨论(0)
  • 2021-01-01 21:11

    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();
    
    0 讨论(0)
提交回复
热议问题