RetrofitWithCoroutineDemo
RetrofitWithCoroutineDemo copied to clipboard
Response body format
The Response body format in this example is :
{
"type":"EN2ZH_CN",
"errorCode":0,
"elapsedTime":1,
"translateResult":[
[
{
"src":"Hello world",
"tgt":"你好,世界"
}
]
]
}
But usually this response body format is :
{
"errorCode":0,
"errorMsg":"",
"result":{
"elapsedTime":1,
"type":"EN2ZH_CN",
"translateResult":[
[
{
"src":"Hello world",
"tgt":"你好,世界"
}
]
]
}
}
And the ApiResult
type is result type
, so how can i fix this ?
you can check this file
https://github.com/ShuangtaoJia/RetrofitWithCoroutineDemo/blob/main/app/src/main/java/com/jst/retrofitwithcoroutine/ui/main/api/TranslateApiService.kt
interface TranslateApiService {
@FormUrlEncoded
@POST("translate?doctype=json")
suspend fun translate(@Field("i")i:String):ApiResult<Result>
}
data class Result(
val type: String,
val elapsedTime: Int,
val translateResult: List<List<TranslateResult>>
) {
data class TranslateResult(
val src:String,
val tgt:String
)
}
object TranslateApi{
val retrofitService: TranslateApiService by lazy { retrofit.create(TranslateApiService::class.java) }
}
the ApiResult
type is not result type,it's a wrapper of successful or failed result ,the result type is Result
,so you can change the content of Result
to fit your json format
and you also need to edit the BusinessErrorInterceptor.kt file to parse the errorCode and errorMsg using your json format
https://github.com/ShuangtaoJia/RetrofitWithCoroutineDemo/blob/main/network/src/main/java/com/jst/network/interceptor/BusinessErrorInterceptor.kt
I explain the principle of this repository in this article,but it's in Chinese,maybe you can translate it.
https://blog.csdn.net/taotao110120119/article/details/110878525
If i want to use the generic type of ApiResult as the result, do you have any idea ?
https://proandroiddev.com/suspend-what-youre-doing-retrofit-has-now-coroutines-support-c65bd09ba067
maybe this article can help you ,this is the basic of "Retrofit + Coroutine"
but this article not cover network error case.
I solve my ploblem by change the generic type of ApiResultCallAdapter<T>
to ApiResultCallAdapter<T: ApiResult<Any>>
, and also change the ApiResult
from scaled class
to Class
, the type
i pass to ApiResultCallAdapter
is ApiResult
.
Also I think there is no need to parse the response code in BusinessErrorInterceptor
, because we can process the response code and http code in delegate.onResponse
, and process ioexception and other exception in delegate.onFailure
.
That's what i do in my project .
Tanks a lot for your work.
I have a solution. Add the following code
sealed class ApiResult<out T> {
data class Success<out T>(val d: T) : ApiResult<T>()
data class Failure(val errorCode: Int, val errorMsg: String) : ApiResult<Nothing>()
}
val <T>ApiResult.Success<BaseBean<T>>.data: T
get() {
return d.data
}
val <T>ApiResult.Success<BaseBean<T>>.errorMsg: String
get() {
return d.msg
}
val <T>ApiResult.Success<BaseBean<T>>.errorCode: Int
get() {
return d.err
}