java.lang.IllegalArgumentException:无法为kotlinx.coroutines.Deferred创建调用适配器

时间:2019-06-06 08:21:16

标签: 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'

今天,我已经在项目中将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()

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

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.

2 个答案:

答案 0 :(得分:3)

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

  

新功能:在Kotlin函数上支持suspend修饰符!这可以让你   以惯用的方式表达HTTP请求的异步性   语言。

     

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

     

在幕后的行为就像定义为好玩的用户(...):   调用,然后使用Call.enqueue进行调用。您也可以返回   用于访问响应元数据的响应。

     

当前,此集成仅支持非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)

答案 1 :(得分:1)

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

之前:

val retrofit = Retrofit.Builder()
                .baseUrl(BuildConfig.BASE_URL)
                .client(httpClient)
                .addConverterFactory(MoshiConverterFactory.create())
                .build()

之后:(工作代码)

val retrofit = Retrofit.Builder()
                .baseUrl(BuildConfig.BASE_URL)
                .client(httpClient)
                .addConverterFactory(MoshiConverterFactory.create())
                .addCallAdapterFactory(CoroutineCallAdapterFactory())
                .build()