为何要用协程
kotlin 中最难的应该就是协程了,它也是我花费时间最多的(前前后后1-2个月),官方文档&他人文章翻阅了无数遍。到现在我都不敢确保我一定能将这个说的很清楚,但是基础的应用&协程的设计理念和部分原理我还是有一些心得的。
什么是协程
- 协程是
kotlin为我们提供的线程切换框架,它和AsyncTask丶RxJava干的事情一样。 - 协程并不会提高效率,只会提高代码的可读性。
- 协程并不是线程,他只负责切换线程。

Android的切换线程历史
先说作用之前,我们来说下 Android 线程切换的的历史。
讲解之前个大家提醒一个实战用例,大伙可以想一想,用下面的线程切换技术你会如何实现呢?
1:一个界面需要2个接口同时请求成功,当2个接口都请求成功的时候渲染界面(注意:2个接口需要在2个线程中请求哦)。
2:1个界面需要2个接口顺序请求,第二个接口需要依赖第一个接口的返回数据做参数。
- 本质 Handler 切换
有人会说:用
Handler切换也挺开心的啊?我用Handler切换线程超级牛B,我连Handler原理都知道的一清二楚的。其实这种方式切换线程的致命缺点就是地狱回调.

- AsyncTask封装
其实
AsyncTask就是对异步任务做了一次封装(好像所有的框架都是封装)。但是治标不治本,还是规避不了地狱回调的问题,还且很多场景无法使用。

- 一直到
RxJava的出现Android的这个问题才有所缓解。当我第一次使用RxJava的时候,我发现这东西真是太好用了,但是我发现这个东西学习成本非常高。操作符的复杂,以及原理都非常难理解。让我RxJava从入门到放弃。
到这里,大家应该发现上面的
3种方案每一种都有一些弊端,相比较最好的方案应该就是RxJava的流失线式的切线程更为的智能,并且异常也能统一管理。
Kotlin的推广带来了新的切线程方案,它可以以同步代码的写法写出异步的功能。
协程的作用
通过上面的讲解,我们知道了所有的线程框架,都想解决一个问题 地狱回调 问题。那么我们理想的线程切换是啥样的呢?来看下伪代码:
void initView() {
// 主线程展示加载Dialog
展示加载Dialog()
// 异步网络请求等待数据返回
val data = 异步请求网络数据()
// 主线程dismissDialog()
消失Dialog()
// 主线程渲染View
主线程根据数据展示修改View状态(data)
}
看上面的伪代码,大家思考下 Java 能实现这样的功能吗?仔细想 Java 是不可能的实现这样的代码,语法根本不支持,Java 中不可能存在异步方法能返回数据。
最终协程就是为了解决这个问题而诞生。哪有人说 Java 不支持,作为儿子的 Kotlin 协程怎么会支持呢?其实 Koltin 能实现这样的代码是因为 Kotlin 的编译器欺骗了你的眼睛。
fun initView() {
启动一个协程 {
// 1:主线程展示加载Dialog
展示加载Dialog()
// 2:异步网络请求,执行一个挂起函数
val data = 异步请求网络数据()
// 3:主线程dismissDialog()
消失Dialog()
}
}
看上方的伪代码,我们首先启动了一个协程,剩下的主要有 3 句代码,第一句代码没啥好说的。
关键在第二句代码 协程 有一个挂起的概念,意思是我执行一个挂起函数,调用我的主线程你可以去干其他事啦,等我干完事情我再通知你,执行我后面的第三句代码。
仔细回味第二句代码的解释有没有类似回调的意思?我们经常写的回调函数的作用,不就是通知我们做完事情了吗?
其实 Kotlin 的协程挂起函数实现原理就是通过回调来实现的。你看似 1 2 3 句代码写在一起,其实在编译后的 Class 字节码并不是写在一起的, Kotlin 的编译器欺骗了你的眼睛。
总结
通过上面的解释,我们最终总结下 Kotlin 的协程?
- 协程的目的是想让我们用同步代码,写出异步功能
- 协程负责帮我们在执行完挂起函数后切换线程
- 挂起函数最终也是通过回调函数来实现的
- 协程写的同步代码看似写在一起,其实最终编译后挂起函数前后的代码是分开的。
最后提醒大家,不要用看 Java 代码的思想,去看 Kotlin 的协程,不然你会进入一个闭环的。因为有时候你眼睛看到的和最终生成的 Java 代码是不一样的,Kotlin 的编译器会欺骗你的眼睛。