【Kotlin 协程】协程的挂起和恢复 ① ( 协程的挂起和恢复概念 | 协程的 suspend 挂起函数 )

2023-03-30 18:04:41 浏览数 (1)

文章目录

  • 一、协程的挂起和恢复概念
  • 二、协程的 suspend 挂起函数

一、协程的挂起和恢复概念


函数 最基本的操作 是 :

  • 调用 call : 通过 函数名或函数地址 调用函数 ;
  • 返回 return : 函数执行完毕后 , 继续执行函数调用的下一行代码 ;

协程 在 调用 call 和 返回 return 基础上 , 又新增了两种 状态 :

  • 挂起 Suspend : 暂停当前执行的协程 , 保存挂起点的局部变量 , 然后执行异步任务 , 后面的代码会得到异步任务执行完毕 , 恢复 Resume 挂起状态后再执行后续代码 ;
  • 恢复 Resume : 暂停的协程 继续执行 ;

如果 没有挂起操作 , 在子线程中执行异步任务后 , 会马上执行后续的代码 , 只是相当于 普通的多线程操作 ;

协程的作用就是 可以 顺序地执行 异步任务 和 主线程任务 , 其执行顺序按照代码顺序执行 ;

挂起 函数 , 只能在 协程体内部 或者 其它挂起函数 中调用 ;

协程外部不允许使用挂起函数 ;

在协程中 , 执行 挂起 Suspend 函数 , 将 挂起点的信息 记录下来 , 然后执行耗时操作 , 执行完毕后 恢复 Resume ;

二、协程的 suspend 挂起函数


声明挂起函数 , 使用 suspendfun 关键字之前 修饰函数 , 如 :

代码语言:javascript复制
public suspend fun Test() {
	// 函数体
}

如果在 函数 A 中调用上述 Test 挂起函数 , 则 函数 A 也必须是 挂起函数 ;

在协程中 , GlobalScope.launch(Dispatcher.Main){} 中 , 可以直接调用挂起函数 ;

挂起 函数 , 只能在 协程体内部 或者 其它挂起函数 中调用 ;

协程外部不允许使用挂起函数 ;

在协程中 , 执行 挂起 Suspend 函数 , 将 挂起点的信息 记录下来 , 然后执行耗时操作 , 执行完毕后 恢复 Resume ;

在如下代码中 , asynTask 是可挂起的异步任务 函数 , 在 Test 函数中调用 asynTask 函数 , Test 函数必须也是 挂起函数 , 需要由 suspend 修饰 ;

代码语言:javascript复制
public suspend fun Test() {
	asynTask()
	updateMain()
}

public suspend fun asynTask() {
	// 子线程中执行异步任务
}

public fun updateMain() {
	// 主线程更新 UI
}

分析上述 挂起 suspend 函数 Test() 的 调用流程 :

执行 suspend fun Test() 函数时 , 该函数会放入 应用主线程 的 栈帧 中 ,

( 此时栈帧内容 : Test 函数 , 左侧是栈底 )

继续执行内部的 suspend fun asynTask() 函数时 , 该函数也是挂起函数 , 先进行 挂起 suspend 操作 ,

( 此时栈帧内容 : Test 函数 | asynTask 函数 , 左侧是栈底 )

然后执行异步任务 , 异步任务执行完毕后 , 恢复 resume suspend fun asynTask() 函数 , 该函数又回到了 主线程 栈帧 中 , 执行完毕后 , 该函数从 栈帧 中移除 ;

( 此时栈帧内容 : Test 函数 , 左侧是栈底 )

栈帧中恢复 suspend fun Test() 函数中 , 继续执行函数的后半部分 updateMain() , 执行主线程更新 UI 内容 ;

( 此时栈帧内容 : Test 函数 | updateMain 函数 , 左侧是栈底 )

0 人点赞