协程搬运工-取消与超时

关注我的公众号 “安安安安卓” 学习更多知识

关于协程分了四部分来写

协程搬运工-上下文和调度器

协程搬运工-组合挂起函数

协程搬运工-取消与超时

协程搬运工-基础

Job的取消

开发中可能经常有这样一种情况,我们在页面协程中执行一个耗时2s的任务获取数据,获取数据成功展示ui。但是有可能一种情况在协程执行到1s的时候我们的页面被用户返回了,协程中请求的数据不再被需要,此时就需要我们取消协程。

下面代码中的job就是可以被取消的

  1. 代码
fun main() = runBlocking {
    val job: Job = launch {
        repeat(20) {//A
            log(A)
            delay(500)//B
            log(B)
        }
    }
    delay(1700)//C
    job.cancel()//D
}
复制代码
  1. 日志
日志:  A
日志:  B
日志:  A
日志:  B
日志:  A
日志:  B
日志:  A
复制代码
  1. 结论

launch协程体调用cancel后可以取消协程

协程的取消是协作的

  1. 所谓的协作在这里指的就是,如果协程内部在执行耗时任务,那么即使我们取消了协程,也需要计算完成才能真正取消

  2. 如果内部使用挂起函数则可以马上响应取消,如下代码:

fun main() = runBlocking {
    val job = launch(Dispatchers.Default) {
        work()
    }
    delay(1300L) // 等待一段时间
    log(B)
    job.cancelAndJoin() // 取消一个作业并且等待它结束
    log(C)
}

suspend fun work() {
    delay(10)
}
复制代码

上面代码中launch方法内部运行了一个work挂起函数,所以当我们cancelAndJoin的时候,协程立马就被取消了。
3. 如果正在进行密集的计算导致无法取消协程,那么其实有其它方法可以实现。比如我们可以在计算中定期判断Job.isActive判断协程是否活跃来决定是否结束计算。cancel后isActive==false

超时

withTimeOut或withTimeOutOrNull可以响应超时

下面分别介绍一下两个方法

withTimeOut

withTimeOut超时的时候会崩溃

  1. 代码
fun main() = runBlocking {
    val result = withTimeout(3*1000){//运行超过3s就超时
        repeat(20){//正常情况repeat需要20s
            log(A)
            delay(1000)
        }
        "重复结束"
    }
    log(result)
    delay(100)
}
复制代码
  1. 日志
日志:  A
日志:  A
日志:  A
Exception in thread "main" kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 3000 ms
复制代码
  1. 结论

withTimeOut可以响应超时,超时的时候会报崩溃日志

withTimeOutOrNull

使用withTimeOutOrNull不会崩溃,超时会返回null
1.代码

将上一个例子做一个小改动即可

fun main() = runBlocking {
    val result = withTimeoutOrNull(3*1000){
        repeat(20){
            log(A)
            delay(1000)
        }
        "重复结束"
    }
    log(result?:"超时了没结果®")
    delay(100)
}
复制代码
  1. 日志
日志:  A
日志:  A
日志:  A
日志:  超时了没结果
复制代码
  1. 结论

withTimeOutOrNull超时不会报错,而且会返回null

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享