Unable to create converter for Retrofit2 Call
abitgen opened this issue · 6 comments
kotlin version - 1.3.70
kotlin Serialization version - 0.20.0
java.lang.IllegalArgumentException: Unable to create converter for retrofit2.Call<T>
for method _myMethod_
at retrofit2.Utils.methodError(Utils.java:52)
at retrofit2.HttpServiceMethod.createResponseConverter(HttpServiceMethod.java:115)
at retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:82)
at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:37)
at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170)
at retrofit2.Retrofit$1.invoke(Retrofit.java:149)
at java.lang.reflect.Proxy.invoke(Proxy.java:813)
at $Proxy0.createSeamlessSubscription(Unknown Source)
at _myPackageFile_(ApiHandler.kt:33)
at _myPackageFile_(AppRepository.kt:10)
at _myPackageFile_.invokeSuspend(HomeViewModel.kt:24)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
Caused by: kotlinx.serialization.SerializationException: Can't locate argument-less serializer for class Call. For generic classes, such as lists, please provide serializer explicitly.
at kotlinx.serialization.PlatformUtilsKt.serializer(PlatformUtils.kt:21)
at kotlinx.serialization.JvmResolvingKt.serializerByTypeToken(JvmResolving.kt:83)
at com.jakewharton.retrofit2.converter.kotlinx.serialization.Factory.responseBodyConverter(Factory.kt:23)
at retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:330)
at retrofit2.Retrofit.responseBodyConverter(Retrofit.java:313)
at retrofit2.HttpServiceMethod.createResponseConverter(HttpServiceMethod.java:113)
at retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:82)
at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:37)
at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170)
at retrofit2.Retrofit$1.invoke(Retrofit.java:149)
at java.lang.reflect.Proxy.invoke(Proxy.java:813)
at $Proxy0.createSeamlessSubscription(Unknown Source)
at io.titan.titan_demo.data.api.ApiHandler.createSeamlessSubscription(ApiHandler.kt:33)
at io.titan.titan_demo.repo.AppRepository.createSeamlessSubscription(AppRepository.kt:10)
at _myPackageFile_$$inlined$switchMap$1$lambda$1.invokeSuspend(HomeViewModel.kt:24)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665) ```
Best guess is you have suspend fun foo(): Call<T>
which you should replace with suspend fun foo(): T
. Without more information it's impossible to tell.
I would like to Call.enqueue
and handle http status codes, so I am using Call. Technically, it should work with Call
right? I will try downgrading kotlin version.
Please provide the full method declaration.
Api
@POST("subscriptions")
suspend fun createSubscription(@Body subscription: SubscriptionData) : Call<SubscriptionResponse>
Response
@Parcelize
@Serializable
data class SubscriptionResponse (
@SerialName("subReferenceId")
val subReferenceId: Int
) : Parcelable , BaseResponse()
@Serializable
open class BaseResponse {
@SerialName("message")
open var message: String = ""
@SerialName("status")
open var status: String = ""
}
Retrofit instance
Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(Json.asConverterFactory(MediaType.get("application/json")))
.build()
In ViewModel
fun create() =
subscriptionData.switchMap {
liveData(Dispatchers.IO) {
if(it!=null) {
emit(Resource.loading(data = null))
appRepository.createSubscription(it) {
this.emit(it)
}
}
}
AppRepository
createSubscription(subscriptionData: SubscriptionData, call : suspend (Resource<SubscriptionResponse>)-> Unit)
You can use either suspend
or Call
, not both. If you want the Response<T>
you can use it as the return type for your suepend
function. If you want to use Call.enqueue
you shouldn't use suspend
modifier.
Basically: Call
and suspend
are two implementations of the same idea, the execution mechanism. You have to choose one.
Thank you :)