- 本文不介绍协程和挂起的基础用法,如需要请移步其他博客。
- 本文主要讲解: kotlin中的协程是什么,协程的作用;挂起是什么,挂起的作用
- 本文全程尽量白话,使得协程和挂起理解起来更容易。
小故事or小事故?
之前面试的时候,有个面试官问了我一个问题:请你说一下协程和线程的区别?
我当时表面无动于衷(内心想着:好家伙,这人不会不知道协程是做啥的吧?为啥要把协程和线程一起拿出来做比较进行提问?好家伙,这公司…emmm)
这个提问方式是不是很眼熟?这位面试官不是个例,提这个问题,只有两种情况:1.他想考我是不是真的懂这两个东西,给我挖的坑让我去跳;2.他没搞懂这两个东西。
至于到底是哪种情况,不做猜测。
它会报错吗?
首先给一段代码,认真思考一下,这段代码会不会报错,为什么?
注:suspendNetWork()是一个网络请求。
viewModelScope.launch(Dispatchers.Main){
val res=suspendNetWork()
}
很多人都可能会认为是:起了一个main线程,然后网络请求,那一定会报错的啊。
答案:不会报错(惊不惊喜,意不意外)
很多人肯定会有疑问,看完接下来的说明,解惑。
协程(viewModelScope)
- kotlin中是否真的实现了协程?
kotlin中是没有真的实现协程的,kotlin的协程是一个Java的线程框架。而Python这些语言有纯粹的协程架构,那才是真协程。
- kotlin协程的作用?
kotlin协程的作用是让开发者切换线程能够切得像协程一样自然,减少回调地狱出现的可能性。
何为回调地狱?
比如一个接口得到数据A后,还要用数据A去请求下一个接口。以致于callback里还有个callback…实际开发中,几个callback嵌套的事,一点也不梦幻,这就是回调地狱。js也是因为这个事,搞出个future和await来的。
- kotlin的协程是如何解决的地域回调?
viewModelScope.launch {
//1.获取结果1
val treeData = treeRepository.getTreeList()
//2.根据结果1的状态去进行2的接口请求
if (treeData is NetResult.Success){
val woodData=treeRepository.getWoodList(treeData.data[0].id)
//3.根据结果2的状态去进行3的接口请求
if (woodData is NetResult.Success){
val codeData=treeRepository.getCodeInfo(woodData.data[0].name)
}
}else{
errorDataLiveData.postValue(ApiResultCode.API_RESULT_NORMAL)
}
}
像这种代码,3个接口,完成一次业务,开发者如果使用回调的话,就未免过于刺激了,就很地狱了。
使用协程后,代码的可读性极强,出现问题很容易就能找到问题所在。
从这里就可以看出那个面试官问题是:线程框架和线程的区别?
一个 进行线程切换的框架,和线程的区别,emm…自行体会吧,反正我觉得挺无厘头的。
挂起(suspend)
- 什么是挂起?
挂起(suspend)就是个关键字而已
- 挂起(suspend)关键字的作用是什么?
挂起这个关键字的作用是,告诉编译器,编译时这个地方要切换线程,处理回调,并且检查,挂起需要在launch中执行。
构建协程函数launch
- launch作用
它代表的是你的线程切换,要切到的位置。
- launch(dispatcher.io)的意思
切回来是io线程,如果是launch(dispatcher.main)则是main线程。
总结整合
- launch代表开启协程操作,即线程切换。
- dispathcer代表在哪里切。
- suspend标记这里需要切。
结合上面的总结内容,这时再来看最上面那段代码是否报错。
viewModelScope.launch(Dispatchers.Main){
val res=suspendNetWork()
}
它的真实意义是:
取回来的结果执行在main线程,而不是说在main线程执行网络请求。所以这段代码是不会报错的。
本阿sweet想说:这都是自学的,可能有很多误区,表达也很白话方式,目的是最大程度的让人看懂。
自己能够对学习的一个总结也是很nice的。不正之处还请各位码友能够指正出来!
欢迎多学习,多交流!