rxLifeScope 及 Async 方法共同使用,调用async方法将导致请求结束回调不被调用
最近项目需要,要将项目的依赖更新一波,其中rxhttp从2.2.x版本更新到2.9.5,其中rxLife中最显著的变化有这几点
为啥被废弃? 1、同一个FragmentActivity/Fragment下,rxLifeScope与lifecycleScope不能共用;同一个ViewModel下,rxLifeScope与viewModelScope不能共用 2、配合RxHttp发请求时,每次都要开启一个协程来捕获异常,这对于再次封装的人,非常不友好; 目前RxHttp的awaitResult操作符一样可以捕获异常,所以rxLifeScope就没了用武之地,是时候退出历史舞台了 3、不能同lifecycleScope或viewModelScope一样,开启协程时,传入CoroutineContext或CoroutineStart参数 亦没有一系列launchXxx方法 4、rxLifeScope配合RxHttp v2.6.6及以上版本发请求时,调用async方法将导致请求结束回调不被调用
其中第4点就影响到原本的项目代码,如下,其中execute是新扩展增加全局业务异常的捕获,其实就是launch方法的二次封装,在2.2.x的版本还正常使用,更新后确实因为几个方法都是用了async的方法,导致没有返回。也将 rxLifeScope 换为 lifecycleScope 试过,问题依旧。
想知道这个具体原因的本质是什么引起的,要继续使用项目当下的这种代码形式又需要做什么改变?望指教
fun refreshContent() {
rxLifeScope.execute({
//先读取缓存数据用于展示
getWarningCardInfo(true)
getDataModuleList(homeModuleAdapter, true)
//真实请求获取最新数据
getWarningCardInfo()
getDataModuleList(homeModuleAdapter)
getTarget(sportStatus)
getArticle()
homeEditModule.isGone = homeModuleAdapter.collection.isNullOrEmpty()
delay(2000)
}, {}, onFinally = { homeRefreshLayout.finishRefresh() })
}
其中一个方法👇
suspend fun getDataModuleList(adapter: HomeDataModuleAdapter, fetchCache: Boolean = false) = coroutineScope {
val user = UserConfigMMKV.user ?: return@coroutineScope
val familyUserId = UserConfigMMKV.selectedFamilyId ?: return@coroutineScope
val params = hashMapOf<String, Any?>()
params["fetchHealth"] = true
params["visible"] = 1
params["mainUserId"] = user.uid
params["familyUserId"] = familyUserId
val list = if (fetchCache) getCacheOnly(Api.Home.HOME_MODULE_LIST, params).toResultArray<CardModule>().tryAwait()
else getListAsync<CardModule>(Api.Home.HOME_MODULE_LIST, params, enableCache = true).tryAwait()
adapter.setData(list)
}
getListAsync👇
suspend inline fun <reified T : Any> CoroutineScope.getListAsync(
method: String,
params: HashMap<String, Any?>,
enableEncrypt: Boolean = true,
enableCache: Boolean = false,
cacheMode: CacheMode = CacheMode.REQUEST_NETWORK_FAILED_READ_CACHE
): Deferred<MutableList<T>> = getRequest(method, params, enableEncrypt, enableCache, cacheMode).toResultArray<T>().async(this)
fun RxLifeScope.execute(
block: suspend CoroutineScope.() -> Unit,
onError: ((Throwable) -> Unit)? = null,
onStart: (() -> Unit)? = null,
onFinally: (() -> Unit)? = null
): Job = launch(block, { e ->
if (e is SessionExpiredException) {
RxHttpPlugins.cancelAll()
CommonApp.obtain<CommonApp>().onAuthExpired()
return@launch
} else {
onError.isNotNull({
it.invoke(e)
}, {
if (e.errorMsg.isEmpty()) ToastKit.show("CODE:${e.errorCode}") else ToastKit.show(e.errorMsg)
})
}
}, onStart, onFinally)
麻烦提供个简单的案例,并简单说明下问题吧