RxAndroid + Retrofit callTimeout 不会触发 onError
RxAndroid + Retrofit callTimeout doesn't trigger onError
我正在使用 RxAndroid + Retrofit 来发出 http 请求。代码如下所示:
Interceptor headerInterceptor = getHeaderInterceptor();
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.callTimeout(5, TimeUnit.SECONDS)
.addInterceptor(headerInterceptor)
.addInterceptor(httpLoggingInterceptor)
.build();
Gson gson = new GsonBuilder()
.setLenient()
.create();
sRetrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
这样使用:
ApiProvider.provideApi(MyApi.class)
.submit(id, mRequest)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
response -> {
Log.w("tag", "success");
},
throwable -> {
Log.w("tag", "error");
}
);
我设置connectTimeout / readTimeout / writeTimeout
为60秒,设置callTimeout
为5秒
我知道这个配置可能不合理,但我只想在5秒后得到一个超时异常,然后Log.w("tag", "error");
可以被调用。
但是,我发现我的测试永远不会调用这条线。如果我将 connectionTimeout
设置为 1 秒,那么将立即调用该行。
那我想让callTimeout触发日志错误行怎么办呢?
至于我所看到的,我认为您的问题可能不在于您为 callTimeout(5, TimeUnit.SECONDS)
设置了多少秒,我认为您的 Rx 流可能已经抛出一些错误,所以流会破坏您可以从这里得到任何回应。但是,您将时间秒数重置为 1 秒,然后重新启动应用程序,这次流不会中断并且您会收到错误消息。
如此简单,再次重新测试它以确保您的流在进入此订阅之前不会中断。
我已经用一些愚蠢的实现进行了测试:
class MainActivity : AppCompatActivity() {
val delayInterceptor = object : Interceptor {
override fun intercept(chain: Interceptor.Chain): okhttp3.Response {
Thread.sleep(6000L)
return chain.proceed(chain.request())
}
}
val client: OkHttpClient = OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.callTimeout(5, TimeUnit.SECONDS)
.addInterceptor(delayInterceptor)
.build()
val retrofit: Retrofit = Retrofit.Builder()
.baseUrl("https://en.wikipedia.org/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
data class Wiki(
@SerializedName("type")
val type: String
)
interface WikiService {
@GET("api/rest_v1/page/random/summary")
fun getRandomSummary(): Single<Wiki>
}
@SuppressLint("CheckResult")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
retrofit.create(WikiService::class.java)
.getRandomSummary()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
Log.d("tag", "success")
}, {
Log.e("tag", "error")
})
}
}
终于找到原因了
我使用的是 com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
,根据其自述文件已弃用:https://github.com/JakeWharton/retrofit2-rxjava2-adapter
This is now DEPRECATED!
Retrofit 2.2 and newer have a first-party call adapter for RxJava 2: https://github.com/square/retrofit/tree/master/retrofit-adapters/rxjava2
切换到 retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
后,一切都开始正常工作了。
顺便说一句,对于任何可能对他们两者之间的区别感兴趣的人来说?附上我在下面找到的关键信息:
我正在使用 RxAndroid + Retrofit 来发出 http 请求。代码如下所示:
Interceptor headerInterceptor = getHeaderInterceptor();
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.callTimeout(5, TimeUnit.SECONDS)
.addInterceptor(headerInterceptor)
.addInterceptor(httpLoggingInterceptor)
.build();
Gson gson = new GsonBuilder()
.setLenient()
.create();
sRetrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
这样使用:
ApiProvider.provideApi(MyApi.class)
.submit(id, mRequest)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
response -> {
Log.w("tag", "success");
},
throwable -> {
Log.w("tag", "error");
}
);
我设置connectTimeout / readTimeout / writeTimeout
为60秒,设置callTimeout
为5秒
我知道这个配置可能不合理,但我只想在5秒后得到一个超时异常,然后Log.w("tag", "error");
可以被调用。
但是,我发现我的测试永远不会调用这条线。如果我将 connectionTimeout
设置为 1 秒,那么将立即调用该行。
那我想让callTimeout触发日志错误行怎么办呢?
至于我所看到的,我认为您的问题可能不在于您为 callTimeout(5, TimeUnit.SECONDS)
设置了多少秒,我认为您的 Rx 流可能已经抛出一些错误,所以流会破坏您可以从这里得到任何回应。但是,您将时间秒数重置为 1 秒,然后重新启动应用程序,这次流不会中断并且您会收到错误消息。
如此简单,再次重新测试它以确保您的流在进入此订阅之前不会中断。
我已经用一些愚蠢的实现进行了测试:
class MainActivity : AppCompatActivity() {
val delayInterceptor = object : Interceptor {
override fun intercept(chain: Interceptor.Chain): okhttp3.Response {
Thread.sleep(6000L)
return chain.proceed(chain.request())
}
}
val client: OkHttpClient = OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.callTimeout(5, TimeUnit.SECONDS)
.addInterceptor(delayInterceptor)
.build()
val retrofit: Retrofit = Retrofit.Builder()
.baseUrl("https://en.wikipedia.org/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
data class Wiki(
@SerializedName("type")
val type: String
)
interface WikiService {
@GET("api/rest_v1/page/random/summary")
fun getRandomSummary(): Single<Wiki>
}
@SuppressLint("CheckResult")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
retrofit.create(WikiService::class.java)
.getRandomSummary()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
Log.d("tag", "success")
}, {
Log.e("tag", "error")
})
}
}
终于找到原因了
我使用的是 com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
,根据其自述文件已弃用:https://github.com/JakeWharton/retrofit2-rxjava2-adapter
This is now DEPRECATED!
Retrofit 2.2 and newer have a first-party call adapter for RxJava 2: https://github.com/square/retrofit/tree/master/retrofit-adapters/rxjava2
切换到 retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
后,一切都开始正常工作了。
顺便说一句,对于任何可能对他们两者之间的区别感兴趣的人来说?附上我在下面找到的关键信息: