美文网首页
使用明确的job来控制协程生命周期

使用明确的job来控制协程生命周期

作者: mihope | 来源:发表于2019-01-22 22:40 被阅读8次

我们把关于contexts\childrenjobs的知识融合到一起,试想我们有一个具备生命周期的对象,但这个对象不是一个协程。例如,在开发Android应用时,为了执行获取网络数据、执行动画等异步操作,我们在activity的里开启了各种协程。为了避免内存泄漏,当activity被销毁时,所有的这些协程必须取消。

通过创建一个Job的实例来控制我们协程的生命周期,把它绑定到activity的生命周期上。在activity被创建时,使用工厂方法Job()创建一个job实例;当activity被销毁时,它如下这样被取消:

class MyActivity : AppCompatActivity(), CoroutineScope {
    lateinit var job: Job
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        job = Job()
    }

    override fun onDestroy() {
        super.onDestroy()
        job.cancel() // Cancel job on activity destroy. After destroy all children jobs will be cancelled automatically
    }

    /*
     * Note how coroutine builders are scoped: if activity is destroyed or any of the launched coroutines
     * in this method throws an exception, then all nested coroutines are cancelled.
     */
    fun loadDataFromUI() = launch { // <- extension on current activity, launched in the main thread
           val ioData = async(Dispatchers.IO) { // <- extension on launch scope, launched in IO dispatcher
               // blocking I/O operation
           }
           // do something else concurrently with I/O
           val data = ioData.await() // wait for result of I/O
           draw(data) // can draw in the main thread
        }
 }

这个activity实现了CoroutineScope接口,我们只需要重写CoroutineScope.coroutineContext属性来指定协程在这个scope内的执行上下文环境context。那么在这个activity里启动协程就不需要再明确指定他们的执行环境context。

这里有一段示意代码

import kotlin.coroutines.*
import kotlinx.coroutines.*

class Activity : CoroutineScope {
    lateinit var job: Job

    fun create() {
        job = Job()
    }

    fun destroy() {
        job.cancel()
    }
    // to be continued ...

    // class Activity continues
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Default + job
    // to be continued ...

    // class Activity continues
    fun doSomething() {
        // launch ten coroutines for a demo, each working for a different time
        repeat(10) { i ->
            launch {
                delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
                println("Coroutine $i is done")
            }
        }
    }
} // class Activity ends

fun main() = runBlocking<Unit> {
    val activity = Activity()
    activity.create() // create an activity
    activity.doSomething() // run test function
    println("Launched coroutines")
    delay(500L) // delay for half a second
    println("Destroying activity!")
    activity.destroy() // cancels all coroutines
    delay(1000) // visually confirm that they don't work    
}

//Launched coroutines
//Coroutine 0 is done
//Coroutine 1 is done
//Destroying activity!

相关概念

协程,是线程中的,也就是说一个线程中可能包含多个协程,协程与协程之间是可以嵌套的

  1. Scope

    用来给协程分组,在同一个CoroutineScope下创建的协程(如果没有显示指定其他Scope),默认都是父子关系,这样的好处在于cancel父协程后,所有的子协程都可以被一起cancel掉。

  2. Context

    当前协程的上下文,用于在协程与协程之间参数传递。

    可以用于声明当前 协程 在哪一个线程中声明,以及当前 协程 被中断后,在哪一个线程中恢复它

  3. Job

    代表了协程本身,协程不仅包含了上下文,其本身还是可执行体。
    任务,封装了协程中需要执行的代码逻辑。Job 可以取消并且有简单生命周期

  4. Dispatcher

    调度器,调度协程运行在哪个线程上。决定协程所在的线程或线程池。它可以指定协程运行于特定的一个线程、一个线程池或者不指定任何线程(这样协程就会运行于当前线程)

  5. withcontext

    不会创建新的协程,在指定协程上运行挂起代码块,并挂起该协程直至代码块运行完成

相关文章

  • 使用明确的job来控制协程生命周期

    我们把关于contexts\children和jobs的知识融合到一起,试想我们有一个具备生命周期的对象,但这个对...

  • kotlin协程之上下文

    CoroutineContext是一组用于定义协程行为的元素 Job:控制协程的生命周期 CoroutineDis...

  • Kotlin 之 协程

    Job: 控制协程的生命周期 CoroutineDispatcher: 向合适的线程分发任务;CoroutineN...

  • 协程的简单使用

    1、协程作用范围。 全局有效。 生命周期内有效。 1、基本使用。 开启同步协程。 输出: 123 开启异步协程。 ...

  • Kotlin-协程核心库分析-Job父子取消

    父Job取消时如何取消子Job 父协程完成结束 我们看下子协程如何被取消的。首先我们需要知道 子协程启动的时候会放...

  • kotlin学习笔记之协程

    前言 整理了协程的基本使用,不深入,适合入门。刚接触协程,不必过于关注定义。协程的生命周期是需要留意的点。 学习资...

  • 使用 select 切换协程

    使用 select 切换协程 从不同的并发执行的协程中获取值可以通过关键字select来完成,它和switch控制...

  • 协程

    一、取消与超时 1.线程取消 2.Job Job是标准库中启动协程后返回的对象,代表着协程本次作业。我们可以判断协...

  • Kotlin协程(3)✔️协程生命周期

    协程的声明周期是通过 Job 的几种状态体现的,Job协程有 6 种状态: 新建状态新建状态主要是通过 launc...

  • 《Unity入门案例-Tanks坦克大战》11-游戏流程控制

    11 游戏流程控制 使用协程来控制游戏流程 11.1 添加MessageText 首先添加一个Text来显示文字 ...

网友评论

      本文标题:使用明确的job来控制协程生命周期

      本文链接:https://www.haomeiwen.com/subject/ffkdjqtx.html