赞
踩
如遇图片无法加载,请点击此链接
协程:协程的目的是为了让多个任务之间更好的协作,解决异步回调嵌,能够以同步的方式编排代码完成异步工作。将异步代码像同步代码一样直观。同时它也是一个并发流程控制的解决方案。
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 }
常见的协程创建方法有
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") }
上面的代码使用的协程调度器为 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") }
这是调度器为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") }
这是调度器为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"
}
因为在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") } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。