当前位置:网站首页>【Android Kotlin协程】利用CoroutineContext实现网络请求失败后重试逻辑
【Android Kotlin协程】利用CoroutineContext实现网络请求失败后重试逻辑
2022-07-06 22:22:00 【程序员小何SS】
前言
在Android开发中有一个典型场景:网络请求失败后重试:一般的逻辑是弹出一个Dialog提醒用户“网络请求失败”,并提供重试的按钮。
如果当前页面只有一个网络请求,那么逻辑就很简单了:只需要再调用一下发起这个网络请求的方法就可以了。而当一个页面有多个网络请求时,我常用的办法为失败回调加状态,根据不同的状态调用不同的方法。但是这个方法不免有些繁琐,也有点不安全。首先,你要额外的增加状态,并将它传来传去。有些情况下,你甚至还需要重新初始化网络请求参数。更要命的是:你还要管理这个状态,一旦管理不善,就会导致调用了不该调用的方法,引入严重的BUG。
直到有一天我看到CoroutineExceptionHandler
,灵光突现——可以使用协程上下文来保存将来可能需要重试的网络请求和Request数据,这样就能解决上面的问题了。
由于我所开发的大多数项目都是采用ViewModel实现网络请求逻辑和UI层的解耦,而网络请求基本上是采用Coroutine+Retrofit的方式实现的,基本上都是使用viewModelScope。
viewModelScope.launch() {
request()
}
viewModelScope本质上是一个ViewModel的扩展函数,利用它可以便捷的在ViewModel创建协程,具体的代码就不展开了。默认情况下,它的CoroutineContext由Job和CoroutineDispatcher组成。而协程的上下文本质上就是一个实现了key-value访问的方式的链表结构。我们可以通过继承AbstractCoroutineContextElement
的方式实现自定义的CoroutineContext上下文:
class RetryCallback(val callback: () -> Unit) : AbstractCoroutineContextElement(RetryCallback) {
companion object Key : CoroutineContext.Key<RetryCallback>
}
紧接着,当网络请求发生异常时借助CoroutineExceptionHandler
获取到我们需要重新执行的操作:
val coroutineExceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
val callback = coroutineContext[RetryCallback]
?.callback
}
紧接着,要将coroutineExceptionHandler添加到发起网络请求的协程上下文里:
viewModelScope.launch(exceptionHandler
+ RetryCallback { request() }) {
request()
}
此时,只要在发起网络请求的页面里获取到callback
,并在点击重试按钮的时候调用它,就能实现重试的逻辑。
进一步对它进行封装并增加失败后自动重试逻辑,创建供ViewModel使用的接口,用来处理网络请求错误的后续逻辑:
interface ViewModelFailed {
/**
* @param throwable:异常信息
* @param callback:需要重试的函数
* */
fun requestFailed(throwable: Throwable, callback: () -> Unit)
}
为它创建扩展函数,用来创建CoroutineExceptionHandler
和RetryCallback
上下文实例:
/**
* @param autoReTry:是否自动重试
* @param callback:需要重试的函数
* */
fun ViewModelFailed.initRetry(autoReTry: Boolean = false, callback: () -> Unit) =
CoroutineExceptionHandler { coroutineContext, throwable ->
val retryCallBack = {
coroutineContext[RetryCallback]
?.callback?.invoke()
}
if (autoReTry) {
//自动开始重试逻辑
onRetry()
retryCallBack.invoke()
} else {
//不自动开始重试,后续操作交给用户决定
requestFailed(throwable) {
retryCallBack
}
}
} + RetryCallback(callback)
ViewModel需要实现ViewModelFailed接口,并在发起网络请求的协程中调用initRetry
方法添加异常处理上下文:
class MainViewViewModel : ViewModel(), ViewModelFailed {
val liveData: MutableLiveData<BaseData> = MutableLiveData()
/**
* @param num:用来演示Request请求数据
* @param repeat:失败后自动重试的次数
* */
fun request(num: Int, repeat: Int = 0) {
liveData.value = BaseData.loading()
viewModelScope.launch(initRetry(repeat > 0) {
request(num,repeat - 1)
}) {
liveData.value = BaseData.success(simulateHttp(num))
}
}
private suspend fun simulateHttp(num: Int) = withContext(Dispatchers.IO) {
//模拟网络请求
...
}
override fun requestFailed(throwable: Throwable, callback: () -> Unit) {
//处理失败逻辑
dialog()
//重试
callback.invoke()
}
override fun onRetry() {
}
}
最后
Android学习是一条漫长的道路,我们要学习的东西不仅仅只有表面的 技术,还要深入底层,弄明白下面的 原理,只有这样,我们才能够提高自己的竞争力,在当今这个竞争激烈的世界里立足。
人生不可能一帆风顺,有高峰自然有低谷,要相信,那些打不倒我们的,终将使我们更强大,要做自己的摆渡人。
我把自己这段时间整理的Android最重要最热门的学习方向资料放在了下方二维码中,里面还有不同方向的自学编程路线、面试题集合/面经、及系列技术文章等。**
资源持续更新中,欢迎大家一起学习和探讨。
边栏推荐
- Run the command once per second in Bash- Run command every second in Bash?
- A simple and beautiful regression table is produced in one line of code~
- Acl2022 | decomposed meta learning small sample named entity recognition
- The easycvr platform is connected to the RTMP protocol, and the interface call prompts how to solve the error of obtaining video recording?
- JS also exports Excel
- Leetcode notes
- mpf2_ Linear programming_ CAPM_ sharpe_ Arbitrage Pricin_ Inversion Gauss Jordan_ Statsmodel_ Pulp_ pLU_ Cholesky_ QR_ Jacobi
- Camera calibration (I): robot hand eye calibration
- R language principal component PCA, factor analysis, clustering analysis of regional economy analysis of Chongqing Economic Indicators
- Introduction to namespace Basics
猜你喜欢
Common methods of list and map
The root file system of buildreoot prompts "depmod:applt not found"
JS also exports Excel
九章云极DataCanvas公司摘获「第五届数字金融创新大赛」最高荣誉!
How to package the parsed Excel data into objects and write this object set into the database?
计数排序基础思路
Chapter 9 Yunji datacanvas company has been ranked top 3 in China's machine learning platform market
3GPP信道模型路损基础知识
Digital chemical plants realize the coexistence of advantages of high quality, low cost and fast efficiency
Tree map: tree view - draw covid-19 array diagram
随机推荐
当 Knative 遇见 WebAssembly
Intel David tuhy: the reason for the success of Intel aoten Technology
赠票速抢|行业大咖纵论软件的质量与效能 QECon大会来啦
Case reward: Intel brings many partners to promote the innovation and development of multi domain AI industry
九章云极DataCanvas公司获评36氪「最受投资人关注的硬核科技企业」
Is there any way to bookmark the code in the visual studio project- Is there a way to bookmark code in a Visual Studio project?
What is JVM? What are the purposes of JVM tuning?
日常工作中程序员最讨厌哪些工作事项?
Data security -- 12 -- Analysis of privacy protection
Advertising attribution: how to measure the value of buying volume?
案例大赏:英特尔携众多合作伙伴推动多领域AI产业创新发展
A picture to understand! Why did the school teach you coding but still not
Windows are not cheap things
一图看懂!为什么学校教了你Coding但还是不会的原因...
Oracle - views and sequences
Thesis landing strategy | how to get started quickly in academic thesis writing
A line of R code draws the population pyramid
Jetson nano配置pytorch深度学习环境//待完善
Digital chemical plants realize the coexistence of advantages of high quality, low cost and fast efficiency
广告归因:买量如何做价值衡量?