假定你对协程(Coroutine)一点儿都不了解。 通过阅读本文看看是否能让你明白协程是怎么一回事。
1. 引子
我之前写过一些协程的文章,很久以前了。那会儿还是很痛苦的,毕竟 kotlinx.coroutines 这样强大的框架还在襁褓当中,于是乎我写的几篇协程的文章几乎就是在告诉大家如何写这样一个框架——那种感觉简直糟糕透了,因为没有几个人会有这样的需求。
这次准备从协程用户(也就是程序员你我他啦)的角度来写一下,希望对大家能有帮助。
2. 需求确认
在开始讲解协程之前,我们需要先确认几件事儿:
-
你用过线程对吧?
-
你写过回调对吧?
-
你用过 RxJava 类似的框架吗?
看下你的答案:
-
如果上面的问题的回答都是 “Yes”,那么太好了,这篇文章非常适合你,因为你已经意识到回调有多么可怕,并且找到了解决方案;
-
如果前两个是 “Yes”,没问题,至少你已经开始用回调了,你是协程潜在的用户;
-
如果只有第一个是 “Yes”,那么,可能你刚刚开始学习线程,那你还是先打好基础再来吧~
3. 一个常规例子
我们通过 Retrofit 发送一个网络请求,其中接口如下:
-
interface GitHubServiceApi {
-
@GET("users/{login}")
-
fun getUser(@Path("login") login: String): Call<User>
-
}
-
-
data class User(val id: String, val name: String, val url: String)
Retrofit 初始化如下:
-
val gitHubServiceApi by lazy {
-
val retrofit = retrofit2.Retrofit.Builder()
-
.baseUrl("https://api.github.com")
-
.addConverterFactory(GsonConverterFactory.create())
-
.build()
-
-
retrofit.create(GitHubServiceApi::class.java)
-
}
那么我们请求网络时:
-
gitHubServiceApi.getUser("bennyhuo").enqueue(object : Callback<User> {
-
override fun onFailure(call: Call<User>, t: Throwable) {
-
handler.post { showError(t) }
-
}
-
-
override fun onResponse(call: Call<User>, response: Response<User>) {
-
handler.post { response.body()?.let(::showUser) ?: showError(NullPointerException()) }
-
}
-
})
请求结果回来之后,我们切换线程到 UI 线程来展示结果。这类代码大量存在于我们的逻辑当中,它有什么问题呢?
-
通过 Lambda 表达式,我们让线程切换变得不是那么明显,但它仍然存在,一旦开发者出现遗漏,这里就会出现问题
-
回调嵌套了两层,看上去倒也没什么,但真实的开发环境中逻辑一定比这个复杂的多,例如登录失败的重试