Android - Использование RxJava с Retrofit вызывает исключение IllegalArgumentException - PullRequest
0 голосов
/ 13 марта 2019

Я пытался использовать RxJava с Retrofit для цепочки сетевых запросов в Android. Но, как я уже сказал в заголовке, это вызывает исключение IllegalArgumentException. Ниже вы можете увидеть мой код, который я написал до сих пор (я также включил импорт и файл Gradle с зависимостями, которые я использую для своего проекта):

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

          }
});

Теперь файл Gradle:

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'

}

Но приложение вылетает, и я получаю следующую ошибку / исключение в LogCat:

03-13 18: 36: 29,190 4128-4128 / com.celik.abdullah.hefuxi11 E / AndroidRuntime: ФАТАЛЬНОЕ ИСКЛЮЧЕНИЕ: главная Процесс: com.celik.abdullah.hefuxi11, PID: 4128 java.lang.IllegalArgumentException: невозможно создать адаптер вызова для rx.Observable для метода CliqueDBApiInterface.getStatementsOfTheClique at retrofit2.Utils.methodError (Utils.java:52) at retrofit2.HttpServiceMethod.createCallAdapter (HttpServiceMethod.java:60) at retrofit2.HttpServiceMethod.parseAnnotations (HttpServiceMethod.java:34) в retrofit2.ServiceMethod.parseAnnotations (ServiceMethod.java:36) в retrofit2.Retrofit.loadServiceMethod (Retrofit.java:168) на retrofit2.Retrofit $ 1.invoke (Retrofit.java:147) в java.lang.reflect.Proxy.invoke (Proxy.java:913) в $ Proxy1.getStatementsOfTheClique (неизвестный источник) на com.celik.abdullah.hefuxi11.adapters.CliqueAdapter $ 1.run (CliqueAdapter.java:124) на android.os.Handler.handleCallback (Handler.java:790) на android.os.Handler.dispatchMessage (Handler.java:99) на android.os.Looper.loop (Looper.java:164) на android.app.ActivityThread.main (ActivityThread.java:6494) в java.lang.reflect.Method.invoke (родной метод) в com.android.internal.os.RuntimeInit $ MethodAndArgsCaller.run (RuntimeInit.java:438) на com.android.internal.os.ZygoteInit.main (ZygoteInit.java:807) Причина: java.lang.IllegalArgumentException: Не удалось найти адаптер вызова для rx.Observable. Пытался: * retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory * retrofit2.CompletableFutureCallAdapterFactory * retrofit2.ExecutorCallAdapterFactory at retrofit2.Retrofit.nextCallAdapter (Retrofit.java:239) на retrofit2.Retrofit.callAdapter (Retrofit.java:203) at retrofit2.HttpServiceMethod.createCallAdapter (HttpServiceMethod.java:58) ... еще 14

Кто-нибудь знает, как решить эту проблему? Я нашел несколько других вопросов об этом исключении и перепробовал все ответы, проиграв / изменив пакеты импорта в файле Gradle, но ничего не помогло. Я также добавляю addCallAdapterFactory (RxJava2CallAdapterFactory.create ()) , когда я создаю экземпляр модификации, но я получаю ту же ошибку.

Заранее спасибо,

Ответы [ 3 ]

2 голосов
/ 14 марта 2019

Вы используете заметки RxJava 1.x и подписчиков.Вы добавили фабрику адаптеров RxJava 2.x в .addCallAdapterFactory(RxJava2CallAdapterFactory.create())

, которую вы должны импортировать из RxJava 2.x

соответственно, вам также необходимо обновить зависимость

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;
2 голосов
/ 14 марта 2019

Да, либо обновите все до RxJava2, либо вы можете использовать RxJava1

, в этом случае ваш импорт будет выглядеть примерно так:

/* 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'

И тогда ваш RetrofitApiInterface будет выглядеть примерно так:

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();
0 голосов
/ 13 марта 2019

Чтобы создать один вызов сразу за другим, используйте оператор flatMap вместо создания Subscriber в вашем методе subscribe().

...