15

我正在使用 Retrofit 为我的异步网络调用返回 rxjava Observable。

我发现自己在重复以下调用:

someApiCall().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())

好像我总是订阅 IO 线程并观察 Android 主线程。这似乎是我发现的所有资源都提倡的最佳实践。也许除了长时间运行的计算之外,我不太明白我们什么时候想要偏离这种模式。

有没有办法通过默认 subscribeOn 和 observeOn 线程来删除这个样板?

这是rxjava 插件的用例吗?(我找不到很多使用它们的例子。)

我可以通过弄乱改造执行器来在网络边界设置默认线程吗?

4

4 回答 4

14

对于Observable响应,Retrofit 当前将 设置为(提供的或默认的)subscribeOn的 HTTP 执行器。RestAdapter这样做是为了将 RxJava 支持填充到现有行为中。

2.0 的计划是提供为两者设置默认值subscribeOnobserveOn显式设置的能力(无论是两者,只有一个,还是两者都不是)。

例如,如果您需要将多个 API 调用链接在一起,您不希望总是希望在主线程上进行观察的一个原因是。

于 2014-07-17T16:45:26.253 回答
6

Retrofit 版本 2.0.0-beta2 (2015-09-28)的更改日志显示,在后台运行需要subscribeOn() 。

修复:Observable 和 Single-based 请求的执行现在行为同步(因此需要 subscribeOn() 在后台运行)。

于 2015-11-25T08:11:24.640 回答
4

的,可以删除这两个调用。

这是改装适配器类,它自动安排两者subscribeOnobservedOn消除每次调用中对样板调用的需要:

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());
        }
    }
}

然后在配置改造时使用这个适配器:

Retrofit.Builder()
    .baseUrl(...)
    .addCallAdapterFactory(RxThreadingCallAdapterFactory.create())

我写了这篇博文,详细介绍了这里发生的事情。

这将删除两个调用,我认为这是样板文件。我认为 Jake 将后台调用链接在一起的场景并不真正适用,因为在这种情况下,我会改进同步调用并且根本不使用调度程序。

于 2016-11-27T12:03:40.260 回答
3

这不是您正在寻找的完整答案,但这至少消除了扶正的负担subscribeOn(Schedulers.io())

retrofit = new Retrofit
            .Builder()
            .baseUrl(app.getUrlBase())
            .client(httpClient)
            .addCallAdapterFactory(
RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()) // <-- default subscribeOn() 
)
                .addConverterFactory(jsonFactory)
                .build();
于 2019-02-09T00:29:55.100 回答