クラスexampleのコールアダプタを作成できません。単純


91

SimpleXmlでretrofit2.0.0-beta1を使用しています。RESTサービスからSimple(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作品でラップすることは知っています。しかし、サービスがビジネスオブジェクトをタイプとして返​​す(そして同期モードで動作する)ようにしたい。

更新

追加の依存関係を追加した後.addCallAdapterFactory(RxJavaCallAdapterFactory.create())、さまざまな回答で示唆されているように、私はまだこのエラーを受け取ります:

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


1
答え@chatlaninコルーチンチェックを使用している人のために
NJ

回答:


68

簡単な答え:Call<Simple>サービスインターフェイスに戻ります。

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

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

ただし、を返したくない場合でも、うまくプレイし、柔軟に対応したいと考えていCallます。これをサポートCallAdapterするために、Call<Simple>にを適応させる方法を知っているはずの、の概念がありSimpleます。

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

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


1
はい、これは確かに正しい答えです:(。最初からそれCall<Simple>が機能する方法を知っています。しかし、私の質問で述べたように、私の好みはSimple(以前のバージョンの場合のように)ただ戻ることです。私の結論は:余分なコードなしでは不可能
rmuller

あなたが提供したリンクCall<Simple> は壊れています。どのパッケージにSimple属していますか?
shyam 2015年

メモ@shyamをありがとう。リンクを更新しました。SimpleOPの質問で言及されているクラスです。リンク先はCall<T>
Hosam Aly 2015年

94

Kotlinコルーチンの場合、この状況は、APIサービス関数をsuspendから呼び出すときのようにマークするのを忘れたときに発生しました。CoroutineScope(Dispatchers.IO).launch{}

使用法:

    val apiService = RetrofitFactory.makeRetrofitService()

    CoroutineScope(Dispatchers.IO).launch {

        val response = apiService.myGetRequest()

        // process response...

    }

ApiService.kt

interface ApiService {

       @GET("/my-get-request")
       suspend fun myGetRequest(): Response<String>
}

あなたは私のライブ仲間を救った
GuilhermeRamos20年

コルーチンを使用している間、関数でサスペンドを使用する必要があります。それはバディに感謝するのに役立ちました
AbubakarRafi20年

それは私のために働いたtnx。サスペンドを追加することがこのエラーの解決策です
mmdreza baqalpour

53

依存関係を追加します。

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>ます。


7
SimpleをCall <Simple>に変更することでうまくいくことを私は知っています。ただし、Callサービスインターフェイスにタイプを導入したくありません
rmuller 2015

また、stackoverflow.comCompletableFuture
questions / 32269064 /を

38

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

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

1
素晴らしいリンク!後で確認します。
rmuller 2015

1
ドキュメントにはまだRestAdapterがあり、Retrofit2.0で最も簡単なリクエストを行う方法の例はありません。エラーが発生しましたRxJavaCallAdapterFactoryを解決できませんでした。最も単純なAndroidhttpリクエストを作成するために数時間を費やしました。彼らが宣伝するほど単純ではないようです。多分彼らはもう少し文書化する必要があります。
ヴラドPandžić

Retrofit 2.0を使用している場合は、RestAdapterの代わりにRetrofitを使用してください。
Himanshu Virmani 2015

5
RxJavaCallAdapterFactoryには、同じリポジトリからのadapter-rxjavaアーティファクトが必要です。 compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1'
Damien Diehl 2015

3
retrofit2のために、あなたは正しい依存関係を使用して確保com.squareup.retrofit2:adapter-rxjava:2.1.0して com.squareup.retrofit2:converter-gson:2.1.0
ジョージ・パパス

16

使用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
                }
            }
        };
    }
}

次にSynchronousCallAdapterFactory、Retrofitに登録するだけで問題が解決するはずです。

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

素晴らしいです、ありがとう。非同期呼び出しアダプタを作成する方法があるかどうか知っていますか?したがって、次のようなサービスを呼び出すことができます。enqueue()とコールバックを使用する代わりに、service.getSimple( "id"、new Adapter(){onFail(){} onSuccess(){}}?
markov00 2016

「CallAdapter.Factoryを実装します」これはインターフェイスではなくクラスですか?
ozmank 2016

@ozmankバージョン2.0.0-beta3ではインターフェースでしたが、バージョン2.1.0ではクラスになりました。より現実的にするために、コードを編集しました。ありがとう。
Mateusz Korwel 2016

@MateuszKorwel常に新しいRuntimeException(e)がスローされます!Simpleの代わりにStringを返したいです。
Dr.jacky 2017

3
これを投稿していただきありがとうございます。この処理Simple getSimple()Response<Simple> getSimple()リクエストに関するライブラリを作成しました:github.com/jaredsburrows/retrofit2-synchronous-adapter
Jared Burrows

13

レトロフィット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);

これは私の設定と同じです。
rmuller 2015

1
また、アダプターを作成するときは、必ず次の行を追加してください。.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
Shayan_Aryan 2016年

解決に失敗しました:com.squareup.retrofit:adapter-rxjava:2.1.0
ozmank 2016

1
@ozmankそのretrofit2、私も私の答えを更新しました。試してみてください
rahulrv 2016

5

IllegalArgumentException:クラスjava.lang.Objectのコールアダプタを作成できません

簡単な答え:次の変更で解決しました

ext.retrofit2Version = '2.4.0' -> '2.6.0'
implementation"com.squareup.retrofit2:retrofit:$retrofit2Version"
implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit2Version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit2Version"

幸運を


4

私の場合、これを使用します

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

これとともに

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

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


2

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

移行中の人、Rxを使用していない人、または同期呼び出しが必要な人のために、呼び出しの例を明確にするために、呼び出しは基本的に応答を置き換えます(ラップします)。

Response<MyObject> createRecord(...);

になります

Call<MyObject> createRecord(...);

ではなく

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

(これでもアダプターが必要です)


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

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

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

MyObject myObj = myApi.createRecord(...).execute().body();

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

}

1

私の場合は

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

コールバックを実装し、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
    }

}

-2

この問題を修正した方法は、これをアプリケーションgradleファイルに追加することでした。構成が設定されていない場合、競合が発生します。ライブラリの安定版リリースで修正される可能性があります。

configurations {
    compile.exclude group: 'stax'
    compile.exclude group: 'xpp3'
}

dependencies {
    compile 'com.squareup.retrofit:retrofit:2.0.0-beta1'
    compile 'com.squareup.retrofit:converter-simplexml:2.0.0-beta1'
}

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

  Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(endPoint)
            .addConverterFactory(SimpleXmlConverterFactory.create())
            .build();

それが役に立てば幸い!


1
これは私の質問とまったく同じ構成です。したがって、何も解決しません:)
rmuller 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.