前言
你还记得是哪一年的 google IO 正式宣布 Kotlin 成为 Android 一级开发语言吗?是 Google IO 2017。如今两年时间过去了 , 站在一名 Android 开发者的角度来看 , Kotlin 的生态环境越来越好了 , 相关的开源项目和学习资料也日渐丰富 , 身边愿意去使用或者试用 Kotlin 的朋友也变多了 。常年混迹掘金的我也能明显感觉到 Kotlin 标签下的文章慢慢变多了(其实仍然少的可怜) 。今年的 Google IO 也放出了 Kotlin First 的口号 , 许多新的 API 和功能特性将优先提供 Kotlin 支持 。所以 , 时至今日 , 实在找不到安卓开发者不学 Kotlin 的理由了 。
今天想聊聊的是 Kotlin Coroutine 。虽然在 Kotlin 发布之初就有了协程 , 但是直到 2018 年的 KotlinConf 大会上 , JetBrain 发布了 Kotlin1.3RC , 这才带来了稳定版的协程 。即使稳定版的协程已经发布了一年之余 , 但是好像并没有足够多的用户 , 至少在我看来是这样 。在我学习协程的各个阶段中 , 遇到问题都鲜有地方可以求助 , 抛到技术群基本就石沉大海了 。基本只能靠一些英文文档来解决问题 。
关于协程的文章我看过很多 , 总结一下 , 无非下面几类 。
第一类是 Medium 上热门文章的翻译 , 其实我也翻译过:
https://juejin.im/post/5cea3ee0f265da1bca51b841说实话 , 这三篇文章的确加深了我对协程的理解 。
https://juejin.im/post/5cee800051882544171c5a2c
https://juejin.im/post/5cf513d3e51d4577407b1ceb
第二类就是官方文档的翻译了 , 我看过至少不下于五个翻译版本 , 还是觉得看 https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html 比较好 , 如果英文看着实在吃力 , 可以对照着 Kotlin 中文站的翻译来阅读 。
在看完官方文档的很长一段时间 , 我几乎只知道 GlobalScope 。的确 , 官方文档上基本从头到尾都是在用 GlobalScope 写示例代码 。所以一部分开发者 , 也包括我自己 , 在写自己的代码时也就直接 GlobalScope 了 。一次偶然的机会才发现其实这样的问题是很大的 。在 Android 中 , 一般是不建议直接使用 GlobalScope 的 。那么 , 在 Android 中应该如何正确使用协程呢?再细分一点 , 如何直接在 Activity 中使用呢?如何配合 ViewModel 、LiveData 、LifeCycle 等使用呢?我会通过简单的示例代码来阐述 Android 上的协程使用 , 你也可以跟着动手敲一敲 。
协程在 Android 上的使用
GlobalScope
在一般的应用场景下 , 我们都希望可以异步进行耗时任务 , 比如网络请求 , 数据处理等等 。当我们离开当前页面的时候 , 也希望可以取消正在进行的异步任务 。这两点 , 也正是使用协程中所需要注意的 。既然不建议直接使用 GlobalScope , 我们就先试验一下使用它会是什么效果 。
private fun launchFromGlobalScope() { GlobalScope.launch(Dispatchers.Main) { val deferred = async(Dispatchers.IO) { // network request delay(3000) "Get it" } globalScope.text = deferred.await() Toast.makeText(ApplicationContext, "GlobalScope", Toast.LENGTH_SHORT).show() }}在 launchFromGlobalScope() 方法中 , 我直接通过 GlobalScope.launch() 启动一个协程 , delay(3000) 模拟网络请求 , 三秒后 , 会弹出一个 Toast 提示 。使用上是没有任何问题的 , 可以正常的弹出 Toast。但是当你执行这个方法之后 , 立即按返回键返回上一页面 , 仍然会弹出 Toast。如果是实际开发中通过网络请求更新页面的话 , 当用户已经不在这个页面了 , 就根本没有必要再去请求了 , 只会浪费资源 。GlobalScope 显然并不符合这一特性 。https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/index.html 中其实也详细说明了 , 如下所示:
Global scope is used to launch top-level coroutines which are operating on the whole application lifetime and are not cancelled prematurely. Another use of the global scope is operators running in Dispatchers.Unconfined, which don’t have any job associated with them.大致意思是 , Global scope 通常用于启动顶级协程 , 这些协程在整个应用程序生命周期内运行 , 不会被过早地被取消 。程序代码通常应该使用自定义的协程作用域 。直接使用 GlobalScope 的 async 或者 launch 方法是强烈不建议的 。
Application code usually should use an application-defined CoroutineScope. Using async or launch on the instance of GlobalScope is highly discouraged.
推荐阅读
- Mysql中ACID的原理?
- 光纤传输基础知识汇总
- 山姆超市停车要钱吗,山姆会员店停车场是免费的吗
- JVM 中发生内存溢出的 8 种原因及解决办法
- 详解python中*号的用法!(含实例:零基础也看能懂)
- 卧龙锅巴是哪的特产,卧龙锅巴为什么火了
- Java 线程在虚拟机中的实现
- 网站排名下降不可怕,可怕的是你不知道其原因
- 腊肉可以用洗洁精洗吗,用洗洁精洗过的腊肉可以吃吗
- 奥利司他减肥药的危害停药后会恢复吗,奥利司他停药后反弹吗
