改造 CallAdapter 以暂停函数,其中 returns for each List<Object> a List<LinkedTreeMap>。如何解决?

Retrofit CallAdapter for suspending functions which returns for each List<Object> a List<LinkedTreeMap>. How to solve it?

我的灵感来自于将此适配器写入 Valery Katkov 的回答

我的 Retrofit 调用适配器能够正确地转换普通对象的 JSON,但是当我期望调用 a List<Object> 时,Retrofit returns me a List<LinkedTreeMap>.它无法解析列表

中的 Object

异常

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.networkcalladapter.Post

CallAdapter 工厂和 CallAdapter

class NetworkCallAdapterFactory : CallAdapter.Factory() {
    override fun get(
        returnType: Type,
        annotations: Array<Annotation>,
        retrofit: Retrofit
    ) = when (getRawType(returnType)) {
        Call::class.java -> {
            val callType = getParameterUpperBound(0, returnType as ParameterizedType)
            when (getRawType(callType)) {
                ResponseNetwork::class.java -> {
                    require(callType is ParameterizedType){ "resource must be paramterized" }
                    val resultType = getParameterUpperBound(0, callType)
                    ResponseNetworkAdapter<Any>(getRawType(resultType))
                }
                else -> null
            }
        }
        else -> null
    }

}

class ResponseNetworkAdapter<T: Any>(
    private val type: Type
) : CallAdapter<T, Call<ResponseNetwork<T>>> {
    override fun responseType() = type
    override fun adapt(call: Call<T>): Call<ResponseNetwork<T>> = ResponseNetworkCall(call)
}


abstract class CallDelegate<TIn, TOut>(
    protected val proxy: Call<TIn>
) : Call<TOut> {
    override fun execute(): Response<TOut> = throw NotImplementedError()
    final override fun enqueue(callback: Callback<TOut>) = enqueueImpl(callback)
    final override fun clone(): Call<TOut> = cloneImpl()

    override fun cancel() = proxy.cancel()
    override fun request(): Request = proxy.request()
    override fun isExecuted() = proxy.isExecuted
    override fun isCanceled() = proxy.isCanceled

    abstract fun enqueueImpl(callback: Callback<TOut>)
    abstract fun cloneImpl(): Call<TOut>
}


class ResponseNetworkCall<T: Any>(proxy: Call<T>) : CallDelegate<T, ResponseNetwork<T>>(proxy) {

    override fun enqueueImpl(callback: Callback<ResponseNetwork<T>>) {

        proxy.enqueue(object : Callback<T> {

            override fun onResponse(call: Call<T>, response: Response<T>) {
                callback.onResponse(this@ResponseNetworkCall, Response.success(ResponseNetwork.create(response)))
            }

            override fun onFailure(call: Call<T>, t: Throwable) {
                callback.onResponse(this@ResponseNetworkCall, Response.success(ResponseNetwork.create(Exception(t))))
            }
        })
    }

    override fun cloneImpl() = ResponseNetworkCall(proxy.clone())
}

响应网络

sealed class ResponseNetwork<T> {

    companion object {

        fun <T> create(error: Exception): ResponseNetworkError<T> {
            return ResponseNetworkError(error)
        }

        fun <T> create(response: Response<T>): ResponseNetwork<T> {
            return if (response.isSuccessful) {
                response.body()?.let {
                    ResponseNetworkSuccess(response.code(), response.headers(), it)
                } ?: ResponseNetworkEmpty(
                    response.code(),
                    response.errorBody()?.string() ?: "unknown error"
                )
            } else {
                val msg = response.errorBody()?.string()
                ResponseNetworkError(Exception(msg))
            }
        }

    }
}

data class ResponseNetworkSuccess<T>(
    val code: Int,
    val header: Headers,
    val body: T
) : ResponseNetwork<T>()

data class ResponseNetworkEmpty<T>(
    val code: Int,
    val message: String
) : ResponseNetwork<T>()

data class ResponseNetworkError<T>(
    val exception: Exception
) : ResponseNetwork<T>()

远程Api

@GET("posts")
    suspend fun getPost(): ResponseNetwork<List<Post>>

改造

Retrofit.Builder()
        .baseUrl("https://jsonplaceholder.typicode.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(NetworkCallAdapterFactory())
        .build()
        .create(RemoteApi::class.java)

Post型号

data class Post(val userId: Int,
                val id: Int,
                val title: String,
                val body: String)

有人理解为什么每当我需要来自网络的列表时,retrofit 总是回到我身边 List<LinkedTreeMap>

你能不能用这个替换你的遥控器 API 并检查一下。

@GET("posts")
suspend fun getPost(): Deferred<Response<ResponseNetwork<List<Post>>>

我修复了 NetworkCallAdapterFactory 中的错误

ResponseNetworkAdapter<Any>((resultType))