协程的挂起与恢复

原理

遇到挂起函数时,会首先返回一个对象(协程内部定义的一个单例类),然后将协程封装成 Continuation 对象传递至挂起函数中,挂起函数需要返回真正结果时再调用 Continuation 的 resumeWith 方法,恢复协程的执行。

Continuation 内部会通过状态机(其实就一个 int 型变量)控制回调时开始执行的位置。这就是挂起与恢复的 Java 实现。

finally 代码块

java 中的 finnaly 比较特殊,即使在 try 中使用了 return 语句,finally 也一定会执行。

那如果 try 中调用了挂起函数,finally 代码块该在何时执行呢?答案是在挂起函数返回真正结果后执行,与调用普通函数一致

原因是:由 kt 生成的 java 代码中并没有使用 finnaly,finally 代码块会放在所有代码后执行

如下绿框中的代码是 finally 代码块中的代码,可以发现它被放到了 invokeSuspend 的最后面,保证是在最后执行

使用 finally 时可能会存在一个问题:如果在 finally 中使用协程,该协程有可能不会被执行。原因在于:如果 try 中代码期间协程被取消了,那么 finally 中的协程就不会在执行(协程不会运行在已取消的 scope 中)。

如下:在 try 执行时如果协程被取消了,deleteFile 永远不会执行到。

kotlin 复制代码
viewModelScope.launch {
    try {
        file.deleteOnExit()
        file.createNewFile()
        val consume = write(file)
    } finally {
        deleteFile(file)
    }
}

解决方式是在 deleteFile 外层使用 withContext(NonCancellable)包裹,但要注意使用该方式时一定要注意内存泄露等:因为该作用域内的协程已经脱离的掌控,没有办法进行取消了。

kotlin 复制代码
withContext(NonCancellable) {
    deleteFile(file)
}
相关推荐
失去的青春---夕阳下的奔跑18 分钟前
Android Studio 2022.2.1.20 汉化教程
android·ide·android studio
技术小甜甜18 分钟前
[Godot][游戏开发] 如何在 Godot 中配置 Android 环境(适配新版 Android Studio)
android·android studio·godot
踏雪羽翼23 分钟前
android studio debug调试出现 IOException异常
android·ide·android studio
ll_god24 分钟前
Android Cameara2 + MediaRecorder 完成录像功能
android·数码相机
全是操作1 小时前
安卓学习笔记-数据存储
android·笔记·学习
zhifanxu1 小时前
Android 异步编程中协程的完整实战示例
android·kotlin
召田最帅boy2 小时前
基于URL弹窗的图片链接生成功能技术实现
android·java·javascript
橙子199110163 小时前
Kotlin 中的数据类型有隐式转换吗?为什么?
android·开发语言·kotlin
一起搞IT吧10 小时前
Camera相机人脸识别系列专题分析之一:人脸识别系列专题SOP及理论知识介绍
android·图像处理·人工智能·数码相机
feifeigo12312 小时前
Docker-compose 编排lnmp(dockerfile) 完成Wordpress
android·docker·容器