Retrofit 2.6.0 例外: java.lang.IllegalArgumentException: kotlinx.coroutines.Deferred の呼び出しアダプターを作成できません 質問する

Retrofit 2.6.0 例外: java.lang.IllegalArgumentException: kotlinx.coroutines.Deferred の呼び出しアダプターを作成できません 質問する

Kotlin コルーチンと Retrofit を使用したプロジェクトがあります。

次のような依存関係がありました:

implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'

今日は更新しました改造2.6.0プロジェクトではhttps://github.com/JakeWharton/retrofit2-kotlin-coroutines-adapter現在は廃止されていると書かれています。https://github.com/square/retrofit/blob/master/CHANGELOG.md#version-260-2019-06-05Retrofit は現在 をサポートしていると書かれていますsuspend

そこで、retrofit2-kotlin-coroutines-adapter:0.9.2Retrofit クライアントで次の行を削除して変更しました。

        retrofit = Retrofit.Builder()
            .baseUrl(SERVER_URL)
            .client(okHttpClient)
            .addConverterFactory(MyGsonFactory.create(gson))
            //.addCallAdapterFactory(CoroutineCallAdapterFactory()) - removed it.
            .build()

実行すると、最初のリクエストで例外がキャッチされます。

java.lang.IllegalArgumentException: Unable to create call adapter for kotlinx.coroutines.Deferred<com.package.model.response.UserInfoResponse>
    for method Api.getUserInfo

私の理解では、 の代わりにCoroutineCallAdapterFactory()を使用できますCallAdapter.Factory()が、これは抽象的です。

Api クラスでリクエストを変更してsuspend先頭に追加する場合:

@FormUrlEncoded
@POST("user/info/")
suspend fun getUserInfo(@Field("token") token: String): Deferred<UserInfoResponse>

override suspend fun getUserInfo(token: String): Deferred<UserInfoResponse> =
    service.getUserInfo(token)

次の例外が発生します:

java.lang.RuntimeException: Unable to invoke no-args constructor for kotlinx.coroutines.Deferred<com.package.model.response.UserInfoResponse>. Registering an InstanceCreator with Gson for this type may fix this problem.

ベストアンサー1

読むhttps://github.com/square/retrofit/blob/master/CHANGELOG.md#version-260-2019-06-05私が見た:

新機能: Kotlin の関数で suspend 修飾子をサポートします。これにより、HTTP リクエストの非同期性を言語の慣用的な方法で表現できるようになります。

@GET("users/{id}") suspend fun user(@Path("id") long id): ユーザー

舞台裏では、これは fun user(...): Call として定義され、Call.enqueue で呼び出されたかのように動作します。応答メタデータにアクセスするために Response を返すこともできます。

現在、この統合では null 以外の応答本文タイプのみがサポートされています。null 許容型のサポートについては、問題 3075 に従ってください。

リクエストを変更したので、以下を追加suspendおよび削除しましたDeferred:

@FormUrlEncoded
@POST("user/info/")
suspend fun getUserInfo(@Field("token") token: String): UserInfoResponse


override suspend fun getUserInfo(token: String): UserInfoResponse =
    service.getUserInfo(token)

次に、インタラクタ内(または単にメソッドが呼び出されたときgetUserInfo(token))で以下を削除しますawait()

override suspend fun getUserInfo(token: String): UserInfoResponse =
    // api.getUserInfo(token).await() - was before.
    api.getUserInfo(token)

アップデート

suspendかつて、PDFファイルをダウンロードする際にAPIクラスで削除する必要があった状況に遭遇しました。Retrofit と Kotlin コルーチンを使用して PDF ファイルをダウンロードするにはどうすればいいですか?

おすすめ記事