web-dev-qa-db-ja.com

クラスexample.Simpleの呼び出しアダプターを作成できません

SimpleXmlでretrofit 2.0.0-beta1を使用しています。 RESTサービスからシンプル(XML)リソースを取得したい。 SimpleXMLを使用したSimpleオブジェクトのマーシャリング/アンマーシャリングは正常に機能します。

このコードを使用する場合(2.0.0以前のコードに変換された形式):

final Retrofit rest = new Retrofit.Builder()
    .addConverterFactory(SimpleXmlConverterFactory.create())
    .baseUrl(endpoint)
    .build();
SimpleService service = rest.create(SimpleService.class);
LOG.info(service.getSimple("572642"));

サービス:

public interface SimpleService {

    @GET("/simple/{id}")
    Simple getSimple(@Path("id") String id);

}

私はこの例外を受け取ります:

Exception in thread "main" Java.lang.IllegalArgumentException: Unable to create call adapter for class example.Simple
    for method SimpleService.getSimple
    at retrofit.Utils.methodError(Utils.Java:201)
    at retrofit.MethodHandler.createCallAdapter(MethodHandler.Java:51)
    at retrofit.MethodHandler.create(MethodHandler.Java:30)
    at retrofit.Retrofit.loadMethodHandler(Retrofit.Java:138)
    at retrofit.Retrofit$1.invoke(Retrofit.Java:127)
    at com.Sun.proxy.$Proxy0.getSimple(Unknown Source)

何が欠けていますか?戻り値の型をCallでラップすると機能することを知っています。しかし、サービスがビジネスオブジェクトをタイプとして返​​す(および同期モードで動作する)ようにしたいのです。

UPDATE

別の回答で示唆されているように、余分な依存関係と.addCallAdapterFactory(RxJavaCallAdapterFactory.create())を追加した後、このエラーが表示されます。

Caused by: Java.lang.IllegalArgumentException: Could not locate call adapter for class simple.Simple. Tried:
 * retrofit.RxJavaCallAdapterFactory
 * retrofit.DefaultCallAdapter$1
64
rmuller

短い答え:サービスインターフェイスで Call<Simple> を返します。

Retrofit 2.0は、サービスインターフェイスのプロキシオブジェクトを作成する方法を探しているようです。これを書くことを期待しています:

public interface SimpleService {
    @GET("/simple/{id}")
    Call<Simple> getSimple(@Path("id") String id);
}

ただし、Callを返したくない場合は、引き続きNiceを再生し、柔軟にしたいです。これをサポートするために、 CallAdapter の概念があり、これはCall<Simple>Simpleに適応させる方法を知っているはずです。

RxJavaCallAdapterFactoryの使用は、rx.Observable<Simple>を返そうとする場合にのみ役立ちます。

最も簡単な解決策は、Retrofitが期待するようにCallを返すことです。本当に必要な場合は、 CallAdapter.Factory と書くこともできます。

50
Hosam Aly

依存関係を追加します。

compile 'com.squareup.retrofit:retrofit:2.0.0-beta1'
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta1'

この方法でアダプターを作成します。

Retrofit rest = new Retrofit.Builder()
    .baseUrl(endpoint)
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    .addConverterFactory(SimpleXmlConverterFactory.create())
    .build();

addCallAdapterFactory ()addConverterFactory ()の両方を呼び出す必要があります。

サービス:

public interface SimpleService {

    @GET("/simple/{id}")
    Call<Simple> getSimple(@Path("id") String id);

}

SimpleCall<Simple>に変更します。

52
shichaohui

新しいRetrofit(2. +)を使用すると、addCallAdapterFactoryを追加する必要があります。これは、通常のものまたはRxJavaCallAdapterFactory(for Observables)にすることができます。両方よりも多く追加できると思います。使用するものを自動的にチェックします。以下の作業例を参照してください。詳細については、 このリンク を確認することもできます。

 Retrofit retrofit = new Retrofit.Builder().baseUrl(ApiConfig.BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .build()
36

retrofit2を使用し、常にretrofit2.Call<T>を返したくない場合は、予想どおり単純型を返す独自のCallAdapter.Factoryを作成する必要があります。単純なコードは次のようになります。

import retrofit2.Call;
import retrofit2.CallAdapter;
import retrofit2.Retrofit;

import Java.lang.annotation.Annotation;
import Java.lang.reflect.Type;

public class SynchronousCallAdapterFactory extends CallAdapter.Factory {
    public static CallAdapter.Factory create() {
        return new SynchronousCallAdapterFactory();
    }

    @Override
    public CallAdapter<Object, Object> get(final Type returnType, Annotation[] annotations, Retrofit retrofit) {
        // if returnType is retrofit2.Call, do nothing
        if (returnType.toString().contains("retrofit2.Call")) {
            return null;
        }

        return new CallAdapter<Object, Object>() {
            @Override
            public Type responseType() {
                return returnType;
            }

            @Override
            public Object adapt(Call<Object> call) {
                try {
                    return call.execute().body();
                } catch (Exception e) {
                    throw new RuntimeException(e); // do something better
                }
            }
        };
    }
}

その後、RetrofitでSynchronousCallAdapterFactoryを登録するだけで問題が解決するはずです。

Retrofit rest = new Retrofit.Builder()
        .baseUrl(endpoint)
        .addConverterFactory(SimpleXmlConverterFactory.create())
        .addCallAdapterFactory(SynchronousCallAdapterFactory.create())
        .build();

その後、retrofit2.Callなしで単純型を返すことができます。

public interface SimpleService {
    @GET("/simple/{id}")
    Simple getSimple(@Path("id") String id);
}
14
Mateusz Korwel

レトロフィット2に次の依存関係を追加します

 compile 'com.squareup.retrofit2:retrofit:2.1.0'

gSONの

 compile 'com.squareup.retrofit2:converter-gson:2.1.0'

オブザーバブル用

compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'

XMLの場合、次の依存関係を含める必要があります。

 compile 'com.squareup.retrofit2:converter-simplexml:2.1.0'

サービスコールを以下のように更新します

final Retrofit rest = new Retrofit.Builder()
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    .addConverterFactory(SimpleXmlConverterFactory.create())
    .baseUrl(endpoint)
    .build();
SimpleService service = rest.create(SimpleService.class);
13
3xplore

私の場合、これを使用して

compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'

これとともに

new Retrofit.Builder().addCallAdapterFactory(RxJava2CallAdapterFactory.create())...

何も機能しなかったときに問題を解決しました

4

Rxを使用せずに移行している人、または同期コールが必要な人のためにCallの例を明確にするために、Callは本質的にResponseを置き換えます(ラップします)。

Response<MyObject> createRecord(...);

になる

Call<MyObject> createRecord(...);

ではなく

Call<Response<MyObject>> createRecord(...);

(まだアダプターが必要です)


呼び出しは、実際に応答を返すので、isSuccessfulを引き続き使用できます。次のようなことができます:

myApi.createRecord(...).execute().isSuccessful()

または、次のようにタイプ(MyObject)にアクセスします。

MyObject myObj = myApi.createRecord(...).execute().body();
1
Nick Cardoso

RxJavaを使用していない場合、改造のためだけにRxJavaを追加することは適切ではありません。 2.5.0にはCompletableFutureのサポートがあり、他のライブラリやアダプターを追加せずに使用できます。

build.gradle.kts

implementation("com.squareup.retrofit2:retrofit:2.5.0")
implementation("com.squareup.retrofit2:retrofit-converters:2.5.0")

Api.kt

interface Api {
    @GET("/resource")
    fun listCompanies(): CompletableFuture<ResourceDto>
}

使用法:

Retrofit.Builder()
   .addConverterFactory(SimpleXmlConverterFactory.create())
   .baseUrl("https://api.example.com")
   .build()
   .create(Api::class.Java)
1
Johannes Barop

私の場合、私は使用しました

com.squareup.retrofit2:adapter-rxjava:2.5.0 //notice rxjava

の代わりに

com.squareup.retrofit2:adapter-rxjava2:2.5.0 //notice rxjava2

com.squareup.retrofit2:adapter-rxjava2:2.5.0を使用する場合は、io.reactivex.rxjava2を使用する必要があります

0
svkaka

コールバックを実装し、onResponse関数からSimpleを取得できます。

public class MainActivity extends Activity implements Callback<Simple> {

    protected void onCreate(Bundle savedInstanceState) {
        final Retrofit rest = new Retrofit.Builder()
                    .addConverterFactory(SimpleXmlConverterFactory.create())
                    .baseUrl(endpoint)
                    .build();
        SimpleService service = rest.create(SimpleService.class);
        Call<Simple> call = service.getSimple("572642");
        //asynchronous call
        call.enqueue(this);

        return true;
    }

    @Override
    public void onResponse(Response<Simple> response, Retrofit retrofit) {
       // response.body() has the return object(s)
    }

    @Override
    public void onFailure(Throwable t) {
        // do something
    }

}
0
Sithu
public interface SimpleService {

  @GET("/simple/{id}")
  Simple getSimple(@Path("id") String id);

}

ネットワークとの通信は別のスレッドで行われるため、それでSimpleを変更する必要があります。

public interface SimpleService {

  @GET("/simple/{id}")
  Call<Simple> getSimple(@Path("id") String id);

}
0
Syed Waqas