当前位置:   article > 正文

kotlin协程详解(一)_lifecyclescope.launchwhencreated

lifecyclescope.launchwhencreated

如遇图片无法加载,请点击此链接
协程:协程的目的是为了让多个任务之间更好的协作,解决异步回调嵌,能够以同步的方式编排代码完成异步工作。将异步代码像同步代码一样直观。同时它也是一个并发流程控制的解决方案。
1.怎么启动协程
协程的启动如下

public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy)
        LazyStandaloneCoroutine(newContext, block) else
        StandaloneCoroutine(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}

public fun <T> CoroutineScope.async(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T
): Deferred<T> {
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy)
        LazyDeferredCoroutine(newContext, block) else
        DeferredCoroutine<T>(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

常见的协程创建方法有

launch是一个CoroutineScope的扩展方法在不阻塞当前线程的情况下启动一个新的协程,并返回Job对象。job对象可以看作协程本身,包含了对协程的控制方法

async方法返回Deffered是job的子类,实际上就是增加了awiat方法,能够让当前协程暂时挂起,暂停往下执行,当await方法有返回值后,会恢复协程,继续往下执行。

Deffered和job都有的方法有

start()手动启动协程

join()等待协程执行完毕

cancel()取消一个协程

CoroutineScope是一个接口,我们通常使用它的实现类GlobalScope这是一个全局的变量。上述方法中第一个参数context是协程的上下文如果我们不传默认会使用EmptyCoroutineContext,经过 newCoroutineContext(context)会返回Default协程运行调度器。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3l83QsRl-1665970992617)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a4eb7d8b683b4cd5a9d6fcc2735bb79a~tplv-k3u1fbpfcp-watermark.image?)]

Disaptchers.IO 显示的指定协程运行的线程为IO线程

Dispathcers.Main 指定这个协程运行在主线程上。

Dispathcers.Default 默认的,启动协程时会启动一个线程

Dispathcers.Unconfined 不指定,在当前线程运行,协程恢复后的运行的线程取决于协程关起时所在的线程。

在协程调度器中needDispatch()方法表示是否需要将协程代码块分发到相应的线程中,其中只有Unconfined不需要分发,因为他是运行在当前线程中。

第二个参数是协程启动的类型

DEFAULT模式表示创建即启动,可随时取消。

ATOMIC自动模式,创建即启动,但是启动前不可取消。

LAZY模式只用当调用start方法后才会启动。

最后一个参数则是我们的闭包代码块

我们来看一下代码

private val TAG = "CoroutineScene"

private suspend fun request1() : String{
    delay(2000)
    Log.e(TAG, "request1 work on Thread ${Thread.currentThread().name}")
    return "request1"
}

private suspend fun request2() : String{
    delay(2000)
    Log.e(TAG, "request2 work on Thread ${Thread.currentThread().name}")
    return "request2"
}

private suspend fun request3(str : String = "") : String{
    delay(2000)
    Log.e(TAG, "request3 work on Thread ${Thread.currentThread().name}")
    return "request3"
}



/**
 * 这种写法异步任务按书写顺序执行
2022-09-02 15:18:38.641 6163-6163/com.example.tdframe E/CoroutineScene: coroutine1
2022-09-02 15:18:38.641 6163-6163/com.example.tdframe E/CoroutineScene: run coroutine1
2022-09-02 15:18:40.645 6163-6163/com.example.tdframe E/CoroutineScene: request1 work on Thread main
2022-09-02 15:18:42.649 6163-6163/com.example.tdframe E/CoroutineScene: request2 work on Thread main
2022-09-02 15:18:44.653 6163-6163/com.example.tdframe E/CoroutineScene: request3 work on Thread main
2022-09-02 15:18:44.653 6163-6163/com.example.tdframe E/CoroutineScene: updateUI r1=request1, r2 = request2, r3 = request3 Thread main
 代码是运行在UI线程上的,延迟代码运行在IO线程
 */
fun coroutine1(){
    GlobalScope.launch(context = Dispatchers.Main) {
        Log.e(TAG, "run coroutine1")
        val r1 = request1()
        val r2 = request2()
        val r3 = request3(r2)
        updateUI(r1, r2, r3)
    }
    Log.e(TAG, "coroutine1")
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

上面的代码使用的协程调度器为 Dispatchers.Main从上面的日志中可以看到Log.e(TAG, “coroutine1”)闭包代码块之外的代码是在之前被低昂用的,因为 Dispatchers.Main最后是通handler让协程运行在主线程上。

/**
2022-09-02 15:36:04.386 6163-6163/com.example.tdframe E/CoroutineScene: coroutine1
2022-09-02 15:36:04.386 6163-6443/com.example.tdframe E/CoroutineScene: run coroutine1, ThreadDefaultDispatcher-worker-1
2022-09-02 15:36:06.388 6163-6443/com.example.tdframe E/CoroutineScene: request1 work on Thread DefaultDispatcher-worker-1
2022-09-02 15:36:08.389 6163-6443/com.example.tdframe E/CoroutineScene: request2 work on Thread DefaultDispatcher-worker-1
2022-09-02 15:36:10.392 6163-6443/com.example.tdframe E/CoroutineScene: request3 work on Thread DefaultDispatcher-worker-1
2022-09-02 15:36:10.392 6163-6443/com.example.tdframe E/CoroutineScene: updateUI r1=request1, r2 = request2, r3 = request3 Thread DefaultDispatcher-worker-1
 */
fun coroutine1(){
    GlobalScope.launch(context = Dispatchers.Default) {
        Log.e(TAG, "run coroutine1, Thread${Thread.currentThread().name}")
        val r1 = request1()
        val r2 = request2()
        val r3 = request3(r2)
        updateUI(r1, r2, r3)
    }
    Log.e(TAG, "coroutine1")
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

这是调度器为Dispatchers.Default代码运行在自带的线程中。

/**
2022-09-02 15:42:20.969 6163-6163/com.example.tdframe E/CoroutineScene: run coroutine1, Threadmain
2022-09-02 15:42:20.969 6163-6163/com.example.tdframe E/CoroutineScene: coroutine1
2022-09-02 15:42:22.972 6163-6705/com.example.tdframe E/CoroutineScene: request1 work on Thread kotlinx.coroutines.DefaultExecutor
2022-09-02 15:42:24.974 6163-6705/com.example.tdframe E/CoroutineScene: request2 work on Thread kotlinx.coroutines.DefaultExecutor
2022-09-02 15:42:26.976 6163-6705/com.example.tdframe E/CoroutineScene: request3 work on Thread kotlinx.coroutines.DefaultExecutor
2022-09-02 15:42:26.976 6163-6705/com.example.tdframe E/CoroutineScene: updateUI r1=request1, r2 = request2, r3 = request3 Thread kotlinx.coroutines.DefaultExecutor
 */
fun coroutine1(){
    GlobalScope.launch(context = Dispatchers.Unconfined) {
        Log.e(TAG, "run coroutine1, Thread${Thread.currentThread().name}")
        val r1 = request1()
        val r2 = request2()
        val r3 = request3(r2)
        updateUI(r1, r2, r3)
    }
    Log.e(TAG, "coroutine1")
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

这是调度器为Dispatchers.Unconfined代码运行的情况,
Log.e(TAG, “run coroutine1, Thread${Thread.currentThread().name}”)这句代码因为是在主线程上调用的所有打印出来是在MainThread上,但是request1中的代码为什么没有运行在住线程中呢

private suspend fun request1() : String{
    delay(2000)
    Log.e(TAG, "request1 work on Thread ${Thread.currentThread().name}")
    return "request1"
}
  • 1
  • 2
  • 3
  • 4
  • 5

因为在request1中我们调用了delay方法,delay方法是在一个默认的线程池中调用,代码执行到delay协程将会被挂起,之后延时结束后将会被恢复,以回调的方式执行接下来的代码。
关于协程的挂起和恢复我将在下一章讲解。

对于Android,jetPack建议我们使用如下方式使用协程,和宿主的生命周期绑定

/**
     * E/CoroutineScene: =================onCreate===================
    E/CoroutineScene: lifecycleScope.launchWhenCreated:whenCreated
    E/CoroutineScene: lifecycle.coroutineScope.launchWhenCreated:whenCreated
    E/CoroutineScene: =================onStart===================
    E/CoroutineScene: lifecycleScope.launchWhenStarted:whenCreated
    E/CoroutineScene: lifecycle.coroutineScope.launchWhenStarted:whenCreated
    E/CoroutineScene: =================onResume===================
    E/CoroutineScene: lifecycleScope.launchWhenResumed:whenCreated
    E/CoroutineScene: lifecycleScope.launchWhenResumed:whenResumed
    lifecycleScope.launchWhenResumed:whenStarted
    E/CoroutineScene: lifecycle.coroutineScope.launchWhenResumed:whenCreated
    lifecycle.coroutineScope.launchWhenResumed:whenResumed
    lifecycle.coroutineScope.launchWhenResumed:whenStarted
    E/CoroutineScene: lifecycleScope.launchWhenCreated:whenResumed
    lifecycleScope.launchWhenCreated:whenStarted
    E/CoroutineScene: lifecycle.coroutineScope.launchWhenCreated:whenResumed
    lifecycle.coroutineScope.launchWhenCreated:whenStarted
    lifecycleScope.launchWhenStarted:whenResumed
    E/CoroutineScene: lifecycleScope.launchWhenStarted:whenStarted
    lifecycle.coroutineScope.launchWhenStarted:whenResumed
    E/CoroutineScene: lifecycle.coroutineScope.launchWhenStarted:whenStarted
     */
    lifecycleScope.launchWhenCreated {
        whenCreated {
            Log.e("CoroutineScene", "lifecycleScope.launchWhenCreated:whenCreated")
        }
        whenResumed {
            Log.e("CoroutineScene", "lifecycleScope.launchWhenCreated:whenResumed")
        }
        whenStarted {
            Log.e("CoroutineScene", "lifecycleScope.launchWhenCreated:whenStarted")
        }
    }

    lifecycle.coroutineScope.launchWhenCreated {
        whenCreated {
            Log.e("CoroutineScene", "lifecycle.coroutineScope.launchWhenCreated:whenCreated")
        }
        whenResumed {
            Log.e("CoroutineScene", "lifecycle.coroutineScope.launchWhenCreated:whenResumed")
        }
        whenStarted {
            Log.e("CoroutineScene", "lifecycle.coroutineScope.launchWhenCreated:whenStarted")
        }
    }
    lifecycleScope.launchWhenResumed {
        whenStarted {
            Log.e("CoroutineScene", "lifecycleScope.launchWhenResumed:whenCreated")
        }
        whenResumed {
            Log.e("CoroutineScene", "lifecycleScope.launchWhenResumed:whenResumed")
        }
        whenStarted {
            Log.e("CoroutineScene", "lifecycleScope.launchWhenResumed:whenStarted")
        }
    }
    lifecycle.coroutineScope.launchWhenResumed {
        whenStarted {
            Log.e("CoroutineScene", "lifecycle.coroutineScope.launchWhenResumed:whenCreated")
        }
        whenResumed {
            Log.e("CoroutineScene", "lifecycle.coroutineScope.launchWhenResumed:whenResumed")
        }
        whenStarted {
            Log.e("CoroutineScene", "lifecycle.coroutineScope.launchWhenResumed:whenStarted")
        }
    }
    lifecycleScope.launchWhenStarted {
        whenStarted {
            Log.e("CoroutineScene", "lifecycleScope.launchWhenStarted:whenCreated")
        }
        whenResumed {
            Log.e("CoroutineScene", "lifecycleScope.launchWhenStarted:whenResumed")
        }
        whenStarted {
            Log.e("CoroutineScene", "lifecycleScope.launchWhenStarted:whenStarted")
        }
    }

    lifecycle.coroutineScope.launchWhenStarted {
        whenStarted {
            Log.e("CoroutineScene", "lifecycle.coroutineScope.launchWhenStarted:whenCreated")
        }
        whenResumed {
            Log.e("CoroutineScene", "lifecycle.coroutineScope.launchWhenStarted:whenResumed")
        }
        whenStarted {
            Log.e("CoroutineScene", "lifecycle.coroutineScope.launchWhenStarted:whenStarted")
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/495670
推荐阅读
相关标签
  

闽ICP备14008679号