Kotlin 学习笔记(十四)浅读协程

上一篇-Kotlin 学习笔记(十三)高阶函数

为什么需要协程

  举例一个异步编程中最常见的场景:后台线程执行一个A任务,下一个B任务依赖于A任务的执行结果,所以必须等待上一个任务执行完成后才能开始执行。直接上代码。

// 模拟本地创建 Token
fun requestToken(cb: (Token) -> Unit){
    //todo
}

//组装Http请求
fun createHttpUtils(token: Token, item: Item, cb: (HttpUtils) -> Unit): {
    //todo 
}

//进行网络请求
fun postUrl(httpUtils: HttpUtils) {
    //todo 
}

  如果在代码中调用 会怎么样呢?

fun postItem() {
    requestToken{ token ->
        createHttpUtils(token) { httpUtils->
            postUrl(httpUtils)
        }
    }
}

   可以看到 我们 嵌套了好几层来实现一个网络请求,可读性变差,代码也很容易出现问题。kotlin中的 协程可以帮助我们减少代码嵌套,优化线程/线程池控制。

协程使用

修改示例的方法,引入kotlin 中的协程我们再看一下 代码会发生哪些变化

// 关于suspend  后边总结,挂起函数的重点
suspend fun requestToken(): Token { ... }   // 挂起函数

 // 挂起函数
suspend fun createHttpUtils(token: Token): HttpUtils{ ... } 

fun postUrl(httpUtils: HttpUtils) { ... }

// 代码使用
fun postItem() {
     //  注意:开发过程中不能直接使用GlobalScope.launch
    GlobalScope.launch {
        // 看似三个任务并行处理的,但其实是串联执行的
        val token = requestToken()
        val httpUtils= createHttpUtils(token)
        postUrl(httpUtils)
    }
}

  上述代码,像代码中的GlobalScope.launch不建议在日常开发中使用,此处只是为了简单代码展示。因为 GlobalScope 创建的协程没有父协程,除非执行完成或手动取消,该协程都会继续运行,而实际上在 Android 中协程的运行需要跟 Activity/Fragment 的生命周期绑定。
  看完上边的代码使用,就已经可以在项目中简单使用了

了解协程

项目中引入

            // 协程    https://github.com/Kotlin/kotlinx.coroutines
            kotlin_coroutines      : [group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-android', version: versions.kotlin_coroutines],
            kotlin_coroutines_core : [group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: versions.kotlin_coroutines],

协程概念

协程通过将复杂性放入库来简化异步编程。程序的逻辑可以在协程中顺序地表达,而底层库会为我们解决其异步性。该库可以将用户代码的相关部分包装为回调、订阅相关事件、在不同线程(甚至不同机器)上调度执行,而代码则保持如同顺序执行一样简单。 - 协程官方文档翻译

  协程的开发人员 Roman Elizarov 如下描述协程的:协程就像非常轻量级的线程。线程是由系统调度的,线程切换或线程阻塞的开销都比较大。而协程依赖于线程,但是协程挂起时不需要阻塞线程,几乎是无代价的,协程是由开发者控制的。所以协程也像用户态的线程,非常轻量级,一个线程中可以创建任意个协程。

协程知识点

根据官方网站了解重要的知识点

挂起函数

//有suspend修饰符标记,这表示两个函数都是挂起函数
suspend fun requestToken(): Token { ... } 
suspend fun createHttpUtils(token: Token): HttpUtils{ ... } 

  挂起函数能够以与普通函数相同的方式获取参数和返回值,但是调用函数可能挂起协程,挂起函数挂起协程时,不会阻塞协程所在的线程。挂起函数执行完成后会恢复协程,后面的代码才会继续执行。但是挂起函数只能在协程中或其他挂起函数中调用。

知识点

   要想明白协程的内在,还是需要看源码

GlobalScope.launch

// launch 函数源码
// CoroutineContext: 协程上下文 是一些元素的集合,包括 Job 和 CoroutineDispatcher 等元素。
// CoroutineDispatcher : 协程调度器,决定协程所在的线程或线程池  (类型 :Dispatchers.Default、Dispatchers.IO、Dispatchers.Main和Dispatchers.Unconfined)
// CoroutineScope.launch 默认使用Dispatchers.Default
public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
    ...
}

对于源码简单的解释 主要看注释部分。

创建方式

  1. CoroutineScope.launch : CoroutineScope.launch {} 是最常用的 Coroutine builders,不阻塞当前线程,在后台创建一个新协程,也可以指定协程调度器
  2. runBlocking : runBlocking {}是创建一个新的协程同时阻塞当前线程,直到协程结束。(个人很少用....)
  3. ** withContext**: withContext {}不会创建新的协程,在指定协程上运行挂起代码块,并挂起该协程直至代码块运行完成。
  4. **async ** : 类似CoroutineScope.launch,区别是 async 返回的Deferred 类型,Deferred 是 Job的子类,带有返回值,但是 CoroutineScope.launch 返回的 Job类型,所以 CoroutineScope.launch没有返回值。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容