一篇文章带你彻底搞懂Kotlin的协程,20年下半年面试
在kotlin里面,对于需要延迟才能返回结果的方法,需要用suspend标明如果在其他线程,需要使用Continuation进行线程切换,可使用suspendCancellableCoroutine 或 suspendCoroutine包裹(前者可取消,相当于后者的扩展),成功调用it.resume(),失败调用it.resumeWithException(Exception()),抛出异常thr
协程的计量单位,相当于一次工作任务,launch方法默认返回一个新的Job
作用于方法上,代表该方法是耗时任务,例如上面的delay方法
public suspend fun delay(timeMillis: Long) {
…
}
主框架($coroutines_version替换为最新版本,如1.3.9,下同)
implementation “org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version”
lifecycleScope(可选,版本2.2.0)
implementation ‘androidx.activity:activity-ktx:$lifecycle_scope_version’
viewModelScope(可选,版本2.3.0-beta01)
implementation “androidx.lifecycle:lifecycle-viewmodel-ktx:$coroutines_viewmodel_version”
先举个简单例子
lifecycleScope.launch {
delay(2000)
tvTest.text=“Test”
}
上面这个例子实现的功能是等待2秒,然后修改id为tvTest的TextView控件的text值为Test
自定义延迟返回方法
在kotlin里面,对于需要延迟才能返回结果的方法,需要用suspend标明
lifecycleScope.launch {
val text=getText()
tvTest.text = text
}
suspend fun getText():String{
delay(2000)
return “getText”
}
如果在其他线程,需要使用Continuation进行线程切换,可使用suspendCancellableCoroutine 或 suspendCoroutine包裹(前者可取消,相当于后者的扩展),成功调用it.resume(),失败调用it.resumeWithException(Exception()),抛出异常
suspend fun getTextInOtherThread() = suspendCancellableCoroutine {
thread {
Thread.sleep(2000)
it.resume(“getText”)
}
}
异常捕获
协程里面的失败都可以通过异常捕获,来统一处理特殊情况
lifecycleScope.launch {
try {
val text=getText()
tvTest.text = text
} catch (e:Exception){
e.printStackTrace()
}
}
取消功能
下面执行了两个job,第一个是原始的,第二个是在1秒后取消第一个job,这会导致tvText的文本并不会改变
val job = lifecycleScope.launch {
try {
val text=getText()
tvTest.text = text
} catch (e:Exception){
e.printStackTrace()
}
}
lifecycleScope.launch {
delay(1000)
job.cancel()
}
设置超时
这个相当于系统封装了自动取消功能,对应函数withTimeout
lifecycleScope.launch {
try {
withTimeout(1000) {
val text = getText()
tvTest.text = text
}
} catch (e:Exception){
e.printStackTrace()
}
}
带返回值的Job
与launch类似的还有一个async方法,它会返回一个Deferred对象,属于Job的扩展类,Deferred可以获取返回的结果,具体使用如下
lifecycleScope.launch {
val one= async {
delay(1000)
return@async 1
}
val two= async {
delay(2000)
return@async 2
}
Log.i(“scope test”,(one.await()+two.await()).toString())
}
自定义CoroutineScope
先看CoroutineScope源码
public interface CoroutineScope {
public val coroutineContext: CoroutineContext
}
CoroutineScope中主要包含一个coroutineContext对象,我们要自定义只需实现coroutineContext的get方法
class TestScope() : CoroutineScope {
override val coroutineContext: CoroutineContext
get() = TODO(“Not yet implemented”)
}
要创建coroutineContext,得要先知道CoroutineContext是什么,我们再看CoroutineContext源码
/**
-
Persistent context for the coroutine. It is an indexed set of [Element] instances.
-
An indexed set is a mix between a set and a map.
-
Every element in this set has a unique [Key].
*/
public interface CoroutineContext {
public operator fun get(key: Key): E?
public fun fold(initial: R, operation: (R, Element) -> R): R
public operator fun plus(context: CoroutineContext): CoroutineContext =
…
public fun minusKey(key: Key<*>): CoroutineContext
public interface Key
public interface Element : CoroutineContext {
…
}
}
通过注释说明,我们知道它本质就是一个包含Element的集合,只是不像set和map集合一样,它自己实现了获取(get),折叠(fold,添加和替换的组合),相减(minusKey,移除),对象组合(plus,如val coroutineContext=coroutineContext1+coroutineContext2)
它的主要内容是Element,而Element的实现有
-
Job 任务
-
ContinuationInterceptor 拦截器
-
AbstractCoroutineContextElement
-
CoroutineExceptionHandler
-
ThreadContextElement
-
DownstreamExceptionElement
-
…
可以看到很多地方都有实现Element,它主要目的是限制范围以及异常的处理。这里我们先了解两个重要的Element,一个是Job,一个是CoroutineDispatcher
Job
-
Job:子Job取消,会导致父job和其他子job被取消;父job取消,所有子job被取消
-
SupervisorJob:父job取消,所有子job被取消
CoroutineDispatcher
-
Dispatchers.Main:主线程执行
-
Dispatchers.IO:IO线程执行
我们模拟一个类似lifecycleScope的自定义TestScope
class TestScope() : CoroutineScope {
override val coroutineContext: CoroutineContext
get() = SupervisorJob() +Dispatchers.Main
}
这里我们定义了一个总流程线SupervisorJob()以及具体执行环境Dispatchers.Main(Android主线程),假如我们想替换掉activity的lifecycleScope,就需要在activity中创建实例
val testScope=TestScope()
然后在activity销毁的时候取消掉所有job
override fun onDestroy() {
testScope.cancel()
super.onDestroy()
}
其他使用方式同lifecycleScope,如
testScope.launch{
val text = getText()
tvTest.text = text
}
深入理解Job
CoroutineScope中包含一个主Job,之后调用的launch或其他方法创建的job都属于CoroutineScope的子Job,每个job都有属于自己的状态,其中包括isActive、isCompleted、isCancelled,以及一些基础操作start()、cancel()、join(),具体的转换流程如下

我们先从创建job开始,当调用launch的时候默认有三个参数CoroutineContext、CoroutineStart以及代码块参数。
-
context:CoroutineContext的对象,默认为CoroutineStart.DEFAULT,会与CoroutineScope的context进行折叠
-
start:CoroutineStart的对象,默认为CoroutineStart.DEFAULT,代表立即执行,同时还有CoroutineStart.LAZY,代表非立即执行,必须调用job的start()才会开始执行
val job2= lifecycleScope.launch(start = CoroutineStart.LAZY) {
delay(2000)
Log.i(“scope test”,“lazy”)
}
job2.start()
当使用这种模式创建时默认就是new状态,此时isActive,isCompleted,isCancelled都为false,当调用start后,转换为active状态,其中只有isActive为true,如果它的任务完成了则会进入Completing状态,此时为等待子job完成,这种状态下还是只有isActive为true,如果所有子job也完成了则会进入Completed状态,只有isCompleted为true。如果在active或Completing状态下出现取消或异常,则会进入Cancelling状态,如果需要取消父job和其他子job则会等待它们取消完成,此时只有isCancelled为true,取消完成后最终进入Cancelled状态,isCancelled和isCompleted都为true
| State | isActive | isCompleted | isCancelled |
| — | — | — | — |
| | | | |
| New | FALSE | FALSE | FALSE |
| Active | TRUE | FALSE | FALSE |
| Completing | TRUE | FALSE | FALSE |
| Cancelling | FALSE | FALSE | TRUE |
| Cancelled | FALSE | TRUE | TRUE |
| Completed | FALSE | TRUE | FALSE |
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。






既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
最后
在此为大家准备了四节优质的Android高级进阶视频:
架构师项目实战——全球首批Android开发者对Android架构的见解
附相关架构及资料

往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
本涵盖了95%以上Android开发知识点,真正体系化!**
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-KthA20xV-1712694559883)]
最后
在此为大家准备了四节优质的Android高级进阶视频:
架构师项目实战——全球首批Android开发者对Android架构的见解
附相关架构及资料
[外链图片转存中…(img-Oxoj2H22-1712694559883)]
往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-EpQCT3gl-1712694559884)]
更多推荐

所有评论(0)