Kotlin Flow 中的运算符重载任务

81 篇文章 2 订阅
10 篇文章 0 订阅
本文详细介绍了Kotlin Flow中retryWhen和retry运算符的使用,包括它们的参数、工作原理及示例。retryWhen允许自定义重试条件,而retry提供了默认重试策略。通过示例代码展示了如何根据异常类型和重试次数控制重试,并演示了如何实现指数退避延迟的重试策略。
摘要由CSDN通过智能技术生成

当我们讨论在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应用程序开发中解决的情况下,两者都可以互换使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值