Search code examples
androidretrofitrx-javaokhttprx-android

RxAndroid + Retrofit callTimeout doesn't trigger onError


I am using RxAndroid + Retrofit to make http request. Code looks like below:

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

Use it like this:

ApiProvider.provideApi(MyApi.class)
                .submit(id, mRequest)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        response -> {
                            Log.w("tag", "success");
                        },
                        throwable -> {
                            Log.w("tag", "error");
                        }
                );

I set connectTimeout / readTimeout / writeTimeout to be 60 seconds, and set callTimeout to be 5 seconds.

I know this configuration may be not reasonable but I just want to get a timeout exception after 5 seconds, and the Log.w("tag", "error"); could be called.

However, I found this line will never be called for my testing. And if I set connectionTimeout to 1 second, then this line will be called immediately.

So what I should do if I want callTimeout to trigger the log error line?


Solution

  • I finally find the the cause.

    I was using com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory, which had been deprecated per its readme: 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
    

    After switching to retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory, everything start working nicely.

    And BTW for any guy who might be interested in what the differences are between them two? Attach the key info I found below:

    enter image description here