Kotlin Flow 中的运算符重载任务
Posted 小陈乱敲代码
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin Flow 中的运算符重载任务相关的知识,希望对你有一定的参考价值。
当我们讨论在Kotlin Flow中使用运算符重载任务时,我们将讨论以下两个运算符:
retryWhen
retry
这两种运算符在大多数情况下都可以互换使用,今天我们将学习它们。
retryWhen
fun <T> Flow<T>.retryWhen(predicate: suspend FlowCollector<T>.(cause: Throwable, attempt: Long) -> Boolean): Flow<T>
并且,我们使用如下运算符:
.retryWhen cause, attempt ->
这里,我们有两个参数,如下所示:
原因:这个cause是可抛出它是所有错误和异常的基类。
尝试:这个attempt表示当前尝试的数字。它从零 。
例如,如果启动任务时出现异常,我们将收到原因(异常)和尝试(0)。
这个retryWhen需要一个谓语函数来决定是否重试。
如果predicate函数返回是的,则只有它会重试,否则它不会。
例如,我们可以这样做:
.retryWhen cause, attempt ->
if (cause is IOException && attempt < 3)
delay(2000)
return@retryWhen true
else
return@retryWhen false
在这种情况下,我们回来了true当原因是IO异常,以及attempt计数小于3 .
因此,只有满足条件时才会重试。
注意:作为predicate函数是挂起函数,可以从中调用另一个挂起函数。
如果我们注意到上面的代码,我们已经调用delay(2000),以便仅在延迟后重试2秒。
retry
fun <T> Flow<T>.retry(
retries: Long = Long.MAX_VALUE,
predicate: suspend (cause: Throwable) -> Boolean = true
): Flow<T>
来自Kotlin流源代码的完整块。
fun <T> Flow<T>.retry(
retries: Long = Long.MAX_VALUE,
predicate: suspend (cause: Throwable) -> Boolean = true
): Flow<T>
require(retries > 0) "Expected positive amount of retries, but had $retries"
return retryWhen cause, attempt -> attempt < retries && predicate(cause)
如果我们看到retry函数,它实际上调用重述时间内部。
retry函数具有默认参数。
如果我们不通过retries,它将使用Long.MAX_值 .
如果我们不通过predicate,它将提供真实的。
例如,我们可以这样做:
.retry()
它将继续重试,直到任务成功完成。
例如,我们也可以这样做:
.retry(3)
它只会重试3。
例如,我们也可以这样做:
.retry(retries = 3) cause ->
if (cause is IOException)
delay(2000)
return@retry true
else
return@retry false
在这里,它变得非常类似于我们使用retryWhen以上。
我们回来了true当原因是IOException。因此,只有当原因是IOException .
如果我们注意到上面的代码,我们已经调用delay(2000),因此仅在延迟2秒后重试。
现在,让我们看看代码示例。
这是一个函数,用于模拟长时间运行的异常任务。
private fun doLongRunningTask(): Flow<Int>
return flow
// your code for doing a long running task
// Added delay, random number, and exception to simulate
delay(2000)
val randomNumber = (0..2).random()
if (randomNumber == 0)
throw IOException()
else if (randomNumber == 1)
throw IndexOutOfBoundsException()
delay(2000)
emit(0)
现在,当使用retry操作
viewModelScope.launch
doLongRunningTask()
.flowOn(Dispatchers.Default)
.retry(retries = 3) cause ->
if (cause is IOException)
delay(2000)
return@retry true
else
return@retry false
.catch
// error
.collect
// success
同样,当使用retryWhen操作
viewModelScope.launch
doLongRunningTask()
.flowOn(Dispatchers.Default)
.retryWhen cause, attempt ->
if (cause is IOException && attempt < 3)
delay(2000)
return@retryWhen true
else
return@retryWhen false
.catch
// error
.collect
// success
如果我们看到,每次我们加上延迟2秒,但在实际的用例中,我们添加了指数退避的延迟。别担心,我们也会执行的。
具有指数退避延迟的重试算子
viewModelScope.launch
var currentDelay = 1000L
val delayFactor = 2
doLongRunningTask()
.flowOn(Dispatchers.Default)
.retry(retries = 3) cause ->
if (cause is IOException)
delay(currentDelay)
currentDelay = (currentDelay * delayFactor)
return@retry true
else
return@retry false
.catch
// error
.collect
// success
在这里,我们创建了两个变量:
电流延迟:这表示要在当前重试中使用的延迟。
延迟因子:我们用这个delayFactor把它乘以电流延迟增加下一次重试的延迟。
就这样,我们实现了具有指数退避延迟的重试。
您可以构建、运行和播放所提供项目中的所有示例。
这样我们就可以使用retry和重述时间解决android应用开发中的有趣问题。请记住,在大多数我们在Android应用程序开发中解决的情况下,两者都可以互换使用。
以上是关于Kotlin Flow 中的运算符重载任务的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin + Flow 实现的 Android 应用初始化任务启动库
Kotlin 扩展函数和运算符重载[第一行代码 Kotlin 学习笔记]
Kotlin 协程Flow 流异常处理 ( 收集元素异常处理 | 使用 try...catch 代码块捕获处理异常 | 发射元素时异常处理 | 使用 Flow#catch 函数捕获处理异常 )
Kotlin 协程Flow 流异常处理 ( 收集元素异常处理 | 使用 try...catch 代码块捕获处理异常 | 发射元素时异常处理 | 使用 Flow#catch 函数捕获处理异常 )