改造 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))
我的灵感来自于将此适配器写入 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))