1

I tried to use RxJava with Retrofit to chain network requests in Android. But as I stated in the title, it causes an IllegalArgumentException. In the following, you can see my code I have written so far(I also included the imports and the gradle file with the dependencies I use for my project):

ApiClient.java :

import retrofit2.Retrofit;

import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Path;
import rx.Observable;


public class ApiClient {

    // trailing slash is needed
    public static final String BASE_URL = "....";

    private static CliqueDBApiInterface sCliqueDBApiInterface;

    public static CliqueDBApiInterface getCliqueDBApiInterface(){

        if(sCliqueDBApiInterface == null){
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build();

            sCliqueDBApiInterface = retrofit.create(CliqueDBApiInterface.class);
        }

        return sCliqueDBApiInterface;
    }

    public interface CliqueDBApiInterface{
        @GET("statementsOfClique/{idOfClique}")
        //Call<ListOfStatements> getStatementsOfTheClique(@Path("idOfClique") int id, @Header("Authorization") String authHeader );
        Observable<ListOfStatements> getStatementsOfTheClique(@Path("idOfClique") int id, @Header("Authorization") String authHeader );
    }

}

MainActivity.java:

import retrofit2.HttpException;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

// ... some other code

Observable<ListOfStatements> call = service.getStatementsOfTheClique(clique.getId(), authenticationToken);

call.subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Subscriber<ListOfStatements>() {
          @Override
          public void onNext(ListOfStatements listOfStatements) {
              // Called once the `ListOfStatements` object is available
              List<Statement> statementList = listOfStatements.getStatementsOfClique();
              // do something with statementList


          }

          @Override
          public void onCompleted() {
             // Nothing to do here
          }

          @Override
          public void onError(Throwable e) {
             if (e instanceof HttpException) {
                int code = ((HttpException) e).code();
             }

          }
});

Now the gradle file:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.celik.abdullah.hefuxi11"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    packagingOptions{
        exclude 'META-INF/rxjava.properties'
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:recyclerview-v7:28.0.0'
    implementation 'com.android.volley:volley:1.1.1'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'com.android.support:cardview-v7:28.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
    implementation 'com.squareup.retrofit2:retrofit:2.5.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
    implementation 'io.reactivex:rxandroid:1.2.0'
    implementation 'io.reactivex:rxjava:1.1.4'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'

}

But the app crashes and I get the following error/exception in the LogCat:

03-13 18:36:29.190 4128-4128/com.celik.abdullah.hefuxi11 E/AndroidRuntime: FATAL EXCEPTION: main Process: com.celik.abdullah.hefuxi11, PID: 4128 java.lang.IllegalArgumentException: Unable to create call adapter for rx.Observable for method CliqueDBApiInterface.getStatementsOfTheClique at retrofit2.Utils.methodError(Utils.java:52) at retrofit2.HttpServiceMethod.createCallAdapter(HttpServiceMethod.java:60) at retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:34) at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:36) at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:168) at retrofit2.Retrofit$1.invoke(Retrofit.java:147) at java.lang.reflect.Proxy.invoke(Proxy.java:913) at $Proxy1.getStatementsOfTheClique(Unknown Source) at com.celik.abdullah.hefuxi11.adapters.CliqueAdapter$1.run(CliqueAdapter.java:124) at android.os.Handler.handleCallback(Handler.java:790) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6494) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for rx.Observable. Tried: * retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory * retrofit2.CompletableFutureCallAdapterFactory * retrofit2.ExecutorCallAdapterFactory at retrofit2.Retrofit.nextCallAdapter(Retrofit.java:239) at retrofit2.Retrofit.callAdapter(Retrofit.java:203) at retrofit2.HttpServiceMethod.createCallAdapter(HttpServiceMethod.java:58) ... 14 more

Do somebody know how to resolve that problem? I have found some other SO questions about this exception and tried all answers by playing/changing the import packages in the gradle file but nothing has worked. I also add the addCallAdapterFactory(RxJava2CallAdapterFactory.create()) when I build the retrofit instance but I got the same error.

Thanks in advance,

3 Answers 3

4

You are using RxJava 1.x observable and subscribers. You have added adapter factory of RxJava 2.x at .addCallAdapterFactory(RxJava2CallAdapterFactory.create())

you should import from RxJava 2.x

accordingly, you need to update dependency as well

implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'io.reactivex.rxjava2:rxjava:2.2.6'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'




import io.reactivex.Observable;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
Sign up to request clarification or add additional context in comments.

Comments

2

Yes, either update everything to RxJava2 or you can use RxJava1

in that case your imports would be something like:

/* rx */
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'io.reactivex:rxjava:1.3.2'

/* retrofit, gson */
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.1'
implementation 'com.squareup.retrofit2:converter-scalars:2.4.0'

And then your RetrofitApiInterface would be something like this:

public static CliqueDBApiInterface getCliqueDBApiInterface(){

    if(sCliqueDBApiInterface == null){
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build();

        sCliqueDBApiInterface = retrofit.create(CliqueDBApiInterface.class);
    }

    return sCliqueDBApiInterface;
}


where okHttpClient = new OkHttpClient.Builder().build();

Comments

0

To create one call right after another, use flatMap operator instead of creating a Subscriber in your subscribe() method.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.