改造2.6.0异常:java.lang.IllegalArgumentException:无法为kotlinx.coroutines.Deferred创建调用适配器

Coo*_*ind 9 android retrofit2 kotlin-coroutines

我有一个Kotlin协程和改造项目。

我有这些依赖项:

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'
Run Code Online (Sandbox Code Playgroud)

今天,我在项目中将Retrofit更新为2.6.0。在https://github.com/JakeWharton/retrofit2-kotlin-coroutines-adapter中,它已被弃用。在https://github.com/square/retrofit/blob/master/CHANGELOG.md#version-260-2019-06-05中写道Retrofit当前支持suspend

因此,我删除了该文件,retrofit2-kotlin-coroutines-adapter:0.9.2并在Retrofit客户端中更改了以下几行:

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

运行时,第一个请求捕获异常:

java.lang.IllegalArgumentException: Unable to create call adapter for kotlinx.coroutines.Deferred<com.package.model.response.UserInfoResponse>
    for method Api.getUserInfo
Run Code Online (Sandbox Code Playgroud)

据我了解,不是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)
Run Code Online (Sandbox Code Playgroud)

我得到这个例外:

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.
Run Code Online (Sandbox Code Playgroud)

Coo*_*ind 10

阅读https://github.com/square/retrofit/blob/master/CHANGELOG.md#version-260-2019-06-05我看到了:

新增:支持Kotlin函数的suspend修饰符!这使您可以以一种惯用的方式来表达HTTP请求的异步性。

@GET(“ users / {id}”)暂停有趣的用户(@Path(“ id”)长id):用户

在幕后,它的行为就像定义为fun user(...):调用,然后使用Call.enqueue进行调用。您还可以返回Response以访问响应元数据。

当前,此集成仅支持非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)
Run Code Online (Sandbox Code Playgroud)

然后在交互器中(或简单地在调用方法时getUserInfo(token))删除await()

override suspend fun getUserInfo(token: String): UserInfoResponse =
    // api.getUserInfo(token).await() - was before.
    api.getUserInfo(token)
Run Code Online (Sandbox Code Playgroud)

更新

一旦我在下载PDF文件时遇到问题,需要suspend在Api类中删除。请参阅如何使用Retrofit和Kotlin协程下载PDF文件?

  • 我的回答简短而切中要害,但您的回答包含来源和所有内容。你可以接受你自己的答案。 (2认同)
  • 我不是为了分数而做的,这很好。我很欣赏你的姿态。 (2认同)

Nic*_*zzi 5

就我而言,我CoroutineCallAdapterFactory在改造初始化中缺少。改造v2.5.0

之前:

val retrofit = Retrofit.Builder()
                .baseUrl(BuildConfig.BASE_URL)
                .client(httpClient)
                .addConverterFactory(MoshiConverterFactory.create())
                .build()
Run Code Online (Sandbox Code Playgroud)

之后:(工作代码)

val retrofit = Retrofit.Builder()
                .baseUrl(BuildConfig.BASE_URL)
                .client(httpClient)
                .addConverterFactory(MoshiConverterFactory.create())
                .addCallAdapterFactory(CoroutineCallAdapterFactory())
                .build()
Run Code Online (Sandbox Code Playgroud)

  • 啊,我明白了。那么,这是有道理的。但我建议升级到2.6.0。请求变得更加简单。 (2认同)
  • 哈,我从 2.5.0 升级到 2.6.0 并捕获了该异常。目前还可以。令人惊讶的是它适用于 2.6.0。 (2认同)