只写只言片语
拒绝胡搅蛮缠
协程本身的定义
协程本身的定义:见wiki(协程)
扔老师的解释是:协程是一种在程序中处理并发任务的方案,也是这种方案的一个组件,与线程属于同一个层级的概念。协程中不存在线程,也不存在并行。
我对此表示认同,因为之前就被公司大哥批评过,纠正了我以前对协程的看法。这是一种协调执行程序的方案,是CPU核心进行的一种并发操作,与线程无关。
并发与并行:并发与并行的区别是什么? – 游小唐的回答 或者 刘志军的回答 – 知乎 (wiki)
Kotlin协程的定义
一个线程框架,没错就是线程框架,本质上与上面的协程没什么关系,可以看做RxJava或者线程池。
为什么用它?
语法糖写起来简单,可以拒绝套娃,方便管理,有利于处理Android生命周期改变导致的内存泄露,以及或许被Google优化后的稍微快一点点。
怎么写?
使用launch()开启协程,指定所在的线程,加上withContext()切换线程:
GlobalScope.launch { println("Coroutines ${Thread.currentThread().name}") }
GlobalScope.launch(Dispatchers.Main) { println("Coroutines ${Thread.currentThread().name}") }
线程的切换处理(带上返回值也是可以的):
GlobalScope.launch(Dispatchers.Main) { ioCode()//会在子线程处理 println("Coroutines ${Thread.currentThread().name}")//会在主线程处理 }
suspend fun ioCode() { withContext(Dispatchers.IO) { //do something println("Coroutines io ${Thread.currentThread().name}") } }
coroutineScope 小知识
伪代码:
mainScope.launch{ coroutineScope{ launch{ // do a } launch{ // do b } } // do c }
coroutineScope这个挂起函数会使得 在 a b 两个协程执行完后再继续执行 c
如何避免协程泄露?
主要靠使用CoroutineScope的一些实现类。
MainScope统一管理:
val mainScope = MainScope() //....// fun someMethod() { mainScope.launch { } } fun someOtherMethod() { mainScope.launch { } } //....// override fun onDestroy() { mainScope.cancel() super.onDestroy() }
直接绑定生命周期,使用lifecycleScope:
lifecycleScope.launch(Dispatchers.Main) {
delay(1000)
Log.d("Coroutines", "1000 毫秒后!")
}
数据的聚合处理(组合挂起函数):
GlobalScope.launch(Dispatchers.Main) {
val one = async { /*network api1*/ return@async "code1" }
val two = async { /*network api1*/ return@async "code2" }
val same = one.await() == two.await()
Log.d("Coroutines", "$same same")
}
使用async配合await可在两处请求均返回后再进行结果处理。
Kotlin是怎么切线程的?
使用suspend关键字对编译时做了处理,对每个块进行了标记,不同线程执行不同代码块,直接在代码里看不到,反编译后可以看一点点。
协程为什么可以挂起却不卡主线程?
哔哩哔哩:【码上开学】Kotlin 协程的挂起好神奇好难懂?今天我把它的皮给扒了
把协程改一改,这样会卡主线程么?
lifecycleScope.launch(Dispatchers.Main) { delay(1000) Log.d("Coroutines", "1000 毫秒后!") }
类比:
thread { Thread.sleep(1000) runOnUiThread { Log.d("Coroutines", "1000 毫秒后!") } }
彩蛋?
方法:
fun classicIoCode(toUiThread: Boolean = true, block: () -> Unit) {}
原始调用:
(::classicIoCode).invoke(true, {})
简化:
(::classicIoCode)(true, {})
简化:
classicIoCode(true, {})
简化:
classicIoCode(true) {}
再简化(使用默认参数):
classicIoCode{}
结语
就这些?嗯,就这些,1块钱的课还想要多少。。。好像还讲了些源码以及配合retrofit,rxJava的,但是忘了,因为要用可以看官方文档啊。
本站由以下主机服务商提供服务支持:
0条评论