Kotlin 协程 (二) ——— 结构化并发

1,884 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

并发任务如果不加以管理,非常容易造成混乱。结构化并发就是为了防止并发任务变得混乱而诞生的概念,它是指将并发任务统一管理,将同等级的并发任务放在同一个作用域中,使其可以统一启动,统一关闭。

一、结构化并发的优点

Kotlin 协程可以方便的实现结构化并发,结构化并发有几个好处:

  • 当任务正在执行时,可以追踪这个任务
  • 当任务不需要执行时,可以取消这个任务
  • 当任务失败时,可以发出错误信号表明有错误发生
  • 统一处理并发任务,避免任务泄漏

二、作用域:CoroutineScope

协程的作用域用于统一管理协程,包括跟踪所有协程和取消所有协程。

常见的协程作用域有:

  • GlobalScope:它是一种顶级协程。生命周期是进程级别的,只要应用进程还在运行,即使 Activity 或 Fragment 被销毁,此作用域下的协程仍然会执行。
  • MainScope:只能在 Activity 中使用,使用 MainScope 时,需要在 onDestroy 中调用 cancel() 取消协程。
  • viewModelScope,只能在 ViewModel 中使用,它会绑定 ViewModel 的生命周期
  • lifecycleScope,只能在 Activity、Fragment 中使用,它会绑定 Activity 和 Fragment 的生命周期。

举个例子,MainScope 的使用:

class MainActivity : AppCompatActivity() {
    private val mainScope = MainScope()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mainScope.launch {
            // do something
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        mainScope.cancel()
    }
}

也可以使用 Kotlin 中的 by 关键字,通过代理模式将 MainActivity 变成 MainScope:

class MainActivity : AppCompatActivity(), CoroutineScope by MainScope() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        launch {
            // do something
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        cancel()
    }
}

三、调度器:Dispatchers

所有的协程都必须在调度器中运行,使用协程的调度器可以方便的切换线程。常见的调度器有三种:

  • Dispatchers.Default 非主线程,用于执行 CPU 密集型任务。常见的 CPU 密集型任务有数组排序、Json 数据解析等。
  • Dispatchers.IO 非主线程,用于执行 IO 密集型任务。常见的 IO 密集型任务有数据库读写、文件读写、网络请求等。
  • Dispatchers.Main 专用于 Android 主线程,用于处理 UI 交互或一些轻量级任务,如展示 UI 控件,更新 LiveData 等。

四、小结

本文介绍了协程的三种调度器:Dispathers.Default、Dispatchers.IO、Dispatchers.Main,使用协程的调度器可以方便地切换线程。 使用协程可以很方便的实现结构化并发,结构化并发的优势在于使并发任务可追踪、可取消、可管理。 使用协程的作用域来统一管理协程,常见的作用域有 GlobalScope、MainScope、viewModelScope、lifecycleScope。