kotlin-笔记05-协程中suspend原理Suspend functions - Kotlin Vocabulary

相关词汇

a finite state:suspend 函数使用1-2-3 3个状态
Continuation:协程挂起函数之间相互通信的方式是Continuation接口对象。
recursively:递归调用


youtube视频链接

Kotlin中的协程简化了Android上的异步操作。在这个视频中,我们将更深入地了解为什么协程是重要的,它们在幕后是如何工作的,协程如何在不阻塞线程的情况下挂起,等等!

Suspend functions - Kotlin Vocabulary

协程Codelab

在 Android 应用中使用 Kotlin 协程


前言

Coroutine are a future of Kotlin that simplify asynchronous operations on Android.
A new suspend modifer was introduced in the language,and it is used for functions that need to be run inside the coroutine.
In this video ,I will tell you more about why coroutines are important and how they work under the hood.
This will help you better understand why a suspend function won't return until all the work that it has started has completed, and also how a coroutine can suspend without blocking threats.
If you learn something new,like the video and subscribe, but only if you think we're earned it.


Use coroutine to manage asynchronous tasks that might otherwise block the main thread and cause you app to freeeze.
使用协程来管理异步任务,否则可能阻塞主线程并导致应用程序冻结。
Coroutines are also helpful to replace callback-based APIs with imperative looking code.
Let's see an example of asynchronous code that uses callbacks.

loginUser-with-callback

Here ,we have the function,loginUser that,after making an echo request to get user information from the internet,it saves the result to the local database and returns the result of that call--all of the using callbacks.

The result of the computation is returns using the userResult callback that is passed in as parameter of the function.

Code that heavily uses callbacks can become hard to read and understand.
Kotlin coroutines let you convert callback-based code to sequential code.
Code read in sequentianlly is typically easier to read and ,unlike callbacks,coroutines provide an easy way to swap between threads and handle exceptions.

See the same function return with coroutines.

2中实现方式比较

We added the suspend modifer to the function,and now it returns user instead of having that callback we used to pass in as a parameter.
As you can see from the wiggly icon in the code there,the other functions call from the suspend function body are also suspend functions.

That suspend modifer tells the compiler that this function needs to be executed inside a coroutine. As a developer,you can think of a suspend function as a regular function whose execution might be suspended and resumed at some point.

If you're new to coroutines in Android and want to learn more about them, I would recommend going throught the coroutine Codelabs first.
But what's the compiler actually doing under the hood when we mark the function as suspend?
Under the hood,the kotlin compiler takes suspended functions and coverts them to an optimized version of callbacks using a finite state machine.

So yes ,you are right,the kotlin compiler will write those callbacks for you.

是的,您是对的,kotlin编译器将为您编写这些回调。(Continuation接口)


Continuation接口

There way suspend functions communicate with each other is continueation objects.
A continuation is just a generic callback interface with some extra information.

  • Context will be the CoroutineContext to be used in that continuation.
  • resumeWith resumes execution of the coroutine with a result that can contian either a value,which is the result of the computation that caused the suspension, or an exception.
kotlin1.3 新增continuation方法

With Kotlin 1.3,you also have convenient extension functions called resume and resumeWithException that are specialized versions of the resumeWith function.

Back to our suspend function,how is compiler is going to modify it ?

kotlin-compiler-rewrite-suspend-function

It will replace the suspend modifier with an extra parmater called completion of type continuation in the function signature.
That will be used to communicate the result of the suspend function computation to the coroutine that called it ,as you can see in the code.
Also,the return type of the transformed function is unit instead of user. The user object will be returned in the added continuation parameter.

Time out.
As a disclaimer,the code we are showing will not fully match bytecode generated by the compiler.
It would be Kotlin code accurate enough to allow you to understand what's really happening internally. This representation is generated by coroutines version 1.3 and might change in future versions of the library.

suspend函数被编译成的代码

Back to the code again.
The kotlin compiler will identify when the function can suspend internally. Every suspension point will be represented as a state in the finite state machine. And these states are represented with lables by the compiler.

suspend函数被编译成的代码2

For a better representation of the state machine, the compiler will use a when statement to implement the different states.

  • Notice that this code is incomplete, since the different states have no may to share information.

How is that problem solved?
The compiler will use the continuation parameter to do it. This is why the generic of the continuation is [inaudible] any instead of the return type of the original function that was user.
The compiler will create a private class that ,first,hold the required data ,and second,calls the loginUser function recursively to resume the execution of the function that was suspended.
Let's see what that class looks like.

image.png

Let's call that generated class,loginUserStateMachine. It is a private class that extends from CoroutineImpl,which is a subtype of continuation. In the constructor,it takes this continuation object,named completion ,that will be used to communicate back the result of this function to the function that called it .

image.png

This is the same continuation that we called before in the last state of the state machine.
But also,this class saves the variables that were declared in the original suspend function.
And there are other variable that are common for all CoroutineImples. The reuslt variable is the result from the previous continuation and label keeps the state of the state machine.

Also,it overrides the invoke suspend function that is used to resume the state machine. It will call the loginUser function to trigger the state machine again.
It calls it with just information of the continuation object.
The rest of parameters in the loginUser function signature become nullable.
At that point ,lable will be already in the next state to execute ,and the result of the previous state's continuation will be assigned.

image.png

An instance of this class is added to loginUser. The first thing it needs to do is knowing if it is the first time the function is called or if the function has resumed from a previious state.
It does it by checking if the continuation passed in is of type loginUserStateMachine or not.
If it's the first time ,it will create a new loginUserStateMachine instance and will store the completion instance received as a parameter.
If it's not ,it will just carry on executing the state machine.

image.png

For completion ,this is what the rest of the function looks like.

image.png

You can see how the rest of code uese the continuation variable to read the result of the last state of the state machine.


image.png

But also ,for every state,it checks if I never happened while this function was suspended.

image.png

In the last state, it calls resume on the continuation of the function that called this one.
And that's it. As you can see, the kotlin compiler does a lot under the hood.
Because of the implementation of the generated state machine,a suspend function won't return until all the work that it has started has completed.

Well,everything needed to resume
How can the code suspend without blocking the thread? the execution of a suspend function is in the continuation object that is passed around,so it can be resumed at any point .
That's all we have to say about suspend for now.
Thanks for watching ,and go write better Android apps with Kotlin.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容

  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 6,044评论 0 4
  • 公元:2019年11月28日19时42分农历:二零一九年 十一月 初三日 戌时干支:己亥乙亥己巳甲戌当月节气:立冬...
    石放阅读 6,877评论 0 2
  • 今天上午陪老妈看病,下午健身房跑步,晚上想想今天还没有断舍离,马上做,衣架和旁边的的布衣架,一看乱乱,又想想自己是...
    影子3623253阅读 2,910评论 1 8