需求背景
应用需要在后台请求一系列的后端接口,采用RxJava或者LiveData形式会存在一系列的observeXXX,如:
interface ITestService {
fun getTest1(): LiveData<BaseResponse<String>>
fun getTest2(): LiveData<BaseResponse<String>>
fun getTest3(): LiveData<BaseResponse<String>>
}
代码调用如下
retrofit.getTest1().observe(activity) {
retrofit.getTest2().observe(activity) {
retrofit.getTest2().observe(activity) {
// do something
}
}
}
可以看出,采用RxJava/LiveData会导致嵌套问题
解决方案1 -- 使用Kotlin协程
利用协程将callback化为直接调用,此方案不在此文讨论范围内
解决方案2 -- 使用同步CallAdapter
2.1 自定义CallAdapter
class MyCallAdapter<R>(private var responseType: Type) :
CallAdapter<R, R> {
override fun responseType(): Type {
return responseType
}
override fun adapt(call: Call<R>): R? {
return try {
val result = call.execute()
result.body()
} catch (e: Exception) {
null
}
}
}
2.2 自定义CallAdapter.Factory
class MyCallAdapterFactory : CallAdapter.Factory() {
override fun get(
returnType: Type,
annotations: Array<out Annotation>,
retrofit: Retrofit
): CallAdapter<*, *> {
return MyCallAdapter<Any>(returnType)
}
}
2.3 初始化Retrofit并使用
interface ITestService {
fun getTest1():BaseResponse<String>
}
val testservice = Retrofit.Builder().client(client())
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(MyCallAdapterFactory())
.build()
.create(ITestService::class.java)
注:若返回结果对BaseResponse包裹了一层,如:
sealed class HttpResult<out T> {
class HttpResultSuccess<T: Any>(val value:T) : HttpResult<T>()
class HttpResultError(val error:Throwable) : HttpResult<Nothing>()
}
interface ITestService {
fun getTest1():HttpResult<BaseResponse<String>>
}
稍加改造即可
class MyCallAdapterFactory : CallAdapter.Factory() {
override fun get(
returnType: Type,
annotations: Array<out Annotation>,
retrofit: Retrofit
): CallAdapter<*, *> {
val realReturnType = getParameterUpperBound(0, returnType as ParameterizedType)
return MyCallAdapter<Any>(realReturnType)
}
}
class MyCallAdapter<R>(private var responseType: Type) :
CallAdapter<R, HttpResult<R>> {
override fun responseType(): Type {
return responseType
}
override fun adapt(call: Call<R>): HttpResult<R> {
try {
val result = call.execute()
if (result.isSuccessful) {
val body = result.body()
if (body != null) {
return HttpResult.HttpResultSuccess(body)
}
}
// 自行处理异常
return HttpResult.HttpResultError(Exception())
} catch (e: Exception) {
return HttpResult.HttpResultError(e)
}
}
}