Okhttp 在与 Retrofit RxJavaCallAdapterFactory 一起使用时忽略 Dispatcher 设置

Okhttp ignores Dispatcher setting when used with Retrofit RxJavaCallAdapterFactory

考虑以下 OkHttp 和 Retrofit 的初始化:

public static SomeServiceRestInterface newRestService(String apiUrl) {
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(apiUrl)
                    .client(createOkHttpClient())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io()))
                    .addConverterFactory(createGsonConverter())
                    .build();
            return retrofit.create(SomeServiceRestInterface.class);
}

private static OkHttpClient createOkHttpClient() {
                    Dispatcher dispatcher = new Dispatcher();
                    dispatcher.setMaxRequestsPerHost(1);
                    dispatcher.setMaxRequests(1);
                    OkHttpClient.Builder builder = new OkHttpClient.Builder()
                                .dispatcher(dispatcher).build()
}

在测试其余调用时,我注意到 Okhttp 根本不支持 setMaxRequestsPerHost 或 setMaxRequests 设置。这是同时发送 3 个请求的日志:

23/07 04:14:22.668 [RxIoScheduler-4] DEBUG - --> POST https://XXX/1 http/1.1
23/07 04:14:22.668 [RxIoScheduler-4] DEBUG - Content-Length: 0
23/07 04:14:22.668 [RxIoScheduler-4] DEBUG - --> END POST (0-byte body)
23/07 04:14:22.672 [RxIoScheduler-7] DEBUG - --> POST https://XXX/2 http/1.1
23/07 04:14:22.673 [RxIoScheduler-7] DEBUG - Content-Length: 0
23/07 04:14:22.673 [RxIoScheduler-7] DEBUG - --> END POST (0-byte body)
23/07 04:14:22.676 [RxIoScheduler-6] DEBUG - --> POST https://XXX/3 http/1.1
23/07 04:14:22.677 [RxIoScheduler-6] DEBUG - Content-Length: 0
23/07 04:14:22.677 [RxIoScheduler-6] DEBUG - --> END POST (0-byte body)

其中 XXX 是同一个域,1/2/3 是不同的路径。

我不确定为什么,但我认为这可能与 addCallAdapterFactory 中设置的 RxJava 调度程序有关。

这是一个错误吗?还是我遗漏了什么?

我正在使用 okhttp 3.4.1 和改造 2.1.0。

在此问题上引用 Jake Wharton 的话:

The implementation of Observable for Retrofit executes requests synchronously relying on the applied Scheduler for any necessarily limiting. If you need the limits from OkHttp's Dispatcher to be honored, then you'll have to write a custom CallAdapter for Observable which uses Call.enqueue instead of Call.execute.

We currently have no plans to support this, although it's likely that Retrofit v3 built on a hypothetical OkHttp v4 might make this the default (though this is a long way off).

This is the same behavior you would see if you used Retrofit's Call and called .execute(), or even used OkHttp's Call with its .execute().

从 retrofit 2.9 开始,RxJavaCallAdapterFactoryRxJava2CallAdapterFactory 的方法 createAsync() 创建了使用 Call.enqueue 的 CallAdapter。这将排队委托给 OkHTTP 的 Dispatcher,因此 maxRequest 设置有效。

create()createWithScheduler() 将使用 Call.execute.

跳过 Dispatcher

对于 RxJava3CallAdapterFactory,名称已交换:create() 现在是异步适配器,而以前的直接执行版本已重命名为 createSynchronous()