跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
Kotlin协程作用域
”︁(章节)
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= Kotlin协程作用域 = == 介绍 == '''Kotlin协程作用域'''(CoroutineScope)是协程结构化并发(Structured Concurrency)的核心机制,它定义了协程的生命周期范围,并确保协程之间的父子关系能够正确管理。作用域的主要职责包括: * 跟踪所有在其内部启动的协程 * 提供取消所有子协程的能力 * 确保当作用域被取消时,所有子协程都会被自动清理 在结构化并发模型中,每个协程都必须在一个作用域内运行,这防止了协程泄漏(coroutine leaks)并简化了资源管理。 == 基本概念 == === 协程作用域的类型 === Kotlin提供了几种预定义的作用域: {| class="wikitable" |- ! 作用域类型 !! 描述 !! 适用场景 |- | GlobalScope || 全局作用域,生命周期与应用程序一致 || 顶级长时间运行的任务(谨慎使用) |- | CoroutineScope || 通用作用域,需手动管理生命周期 || 大多数业务场景 |- | MainScope || 主线程作用域(UI线程) || Android/桌面应用UI操作 |- | viewModelScope || Android ViewModel专用作用域 || Android MVVM架构 |- | lifecycleScope || 与生命周期组件绑定的作用域 || Android生命周期感知操作 |} === 创建自定义作用域 === 通过<code>CoroutineScope()</code>工厂函数创建作用域时需要指定协程上下文: <syntaxhighlight lang="kotlin"> // 创建带有IO调度器的自定义作用域 val customScope = CoroutineScope(Dispatchers.IO + Job()) // 使用作用域启动协程 customScope.launch { // 协程体 } // 取消作用域及其所有子协程 customScope.cancel() </syntaxhighlight> == 父子关系与结构化并发 == === 协程层次结构 === 当在一个协程中启动另一个协程时,会自动建立父子关系: <mermaid> graph TD Parent[父协程] --> Child1[子协程1] Parent --> Child2[子协程2] Child1 --> GrandChild[孙子协程] </mermaid> 这种关系带来两个关键特性: 1. 父协程取消时,所有子协程会自动取消 2. 父协程会等待所有子协程完成后再完成自己 === 代码示例 === <syntaxhighlight lang="kotlin"> fun main() = runBlocking { val parentJob = launch { // 子协程1 launch { repeat(5) { i -> println("Child 1: $i") delay(100) } } // 子协程2 launch { repeat(5) { i -> println("Child 2: $i") delay(150) } } } delay(250) println("Cancelling parent") parentJob.cancel() // 会取消所有子协程 parentJob.join() println("Parent completed") } </syntaxhighlight> '''输出:''' <pre> Child 1: 0 Child 2: 0 Child 1: 1 Child 2: 1 Child 1: 2 Cancelling parent Parent completed </pre> == 作用域构建器 == Kotlin提供了几种作用域构建器来创建临时作用域: === coroutineScope === 创建一个独立的作用域,会等待所有子协程完成后才完成: <syntaxhighlight lang="kotlin"> suspend fun fetchUserData() = coroutineScope { val userProfile = async { fetchProfile() } val userFriends = async { fetchFriends() } UserData( profile = userProfile.await(), friends = userFriends.await() ) } </syntaxhighlight> === supervisorScope === 创建一个监督作用域,子协程的失败不会影响其他子协程: <syntaxhighlight lang="kotlin"> suspend fun processTasks() = supervisorScope { val task1 = launch { processTask1() } // 如果失败 val task2 = launch { processTask2() } // 仍会继续执行 task1.join() task2.join() } </syntaxhighlight> == 实际应用案例 == === Android Activity中的使用 === 在Android中正确处理协程生命周期: <syntaxhighlight lang="kotlin"> class MainActivity : AppCompatActivity() { private val scope = CoroutineScope(Dispatchers.Main + Job()) override fun onDestroy() { super.onDestroy() scope.cancel() // 避免内存泄漏 } fun loadData() { scope.launch { val data = withContext(Dispatchers.IO) { repository.fetchData() } updateUI(data) } } } </syntaxhighlight> === 网络请求组合 === 并行执行多个网络请求: <syntaxhighlight lang="kotlin"> suspend fun fetchDashboardData(): DashboardData = coroutineScope { val userDeferred = async { api.getUser() } val newsDeferred = async { api.getNews() } val adsDeferred = async { api.getAds() } DashboardData( user = userDeferred.await(), news = newsDeferred.await(), ads = adsDeferred.await() ) } </syntaxhighlight> == 数学表示 == 协程作用域可以形式化表示为: <math> Scope = (Context, \{Child_1, Child_2, ..., Child_n\}) </math> 其中取消操作遵循: <math> cancel(Scope) \Rightarrow \forall child \in \{Child_1, ..., Child_n\}: cancel(child) </math> == 最佳实践 == * 避免使用GlobalScope,除非是应用程序级别的长时间运行任务 * 对于UI组件,使用与生命周期绑定的作用域(如Android的lifecycleScope) * 对于ViewModel,使用viewModelScope * 在挂起函数中需要启动协程时,优先使用coroutineScope或supervisorScope * 总是确保作用域在不再需要时被取消 == 常见问题 == '''Q: 为什么我的协程在Activity销毁后还在运行?''' A: 可能是因为使用了GlobalScope或忘记取消自定义作用域。应该使用与生命周期绑定的作用域。 '''Q: coroutineScope和supervisorScope有什么区别?''' A: coroutineScope在子协程失败时会取消所有子协程,而supervisorScope允许其他子协程继续运行。 '''Q: 如何测试带有作用域的代码?''' A: 可以使用TestCoroutineScope(kotlinx-coroutines-test库)来控制虚拟时间进行测试。 [[Category:编程语言]] [[Category:Kotlin]] [[Category:Kotlin协程]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)