当前位置:网站首页>Deep understanding of continuation principle
Deep understanding of continuation principle
2022-06-30 09:02:00 【Byte station】
1. Preface
This is the first update since the new year , I'd like to give you a good old age , I wish you all the best in the new year , At the same time, thank you for your continuous support and help . This article was actually conceived before the Spring Festival , I wanted to finish it during the Chinese New Year in Beijing , Due to plan change , I went back to my hometown for the Spring Festival , During the Spring Festival, I spent most of my time visiting relatives , The article was shelved .
Gossip and less narration , In this article, I will try to make it clear to you ,Kotlin How to realize asynchronous calling in a synchronous way . I believe many students can say one or more of the following concepts .
- Kotlin suspend keyword
- Kotlin Inside Continuation Mechanism
- Continuation Passing Style (CPS) Mechanism
- Finite state machine mechanism
If you've seen it Kotlin Collaborative architects Deep dive into Coroutines on JVM Speech Video , I believe you will not be unfamiliar with the above concepts .
Video link https://www.youtube.com/watch?v=YrrUCSi72E8&t=1329s
But if you don't delve into the source code to see how it works , I believe you know a little about the above concepts . This article will lead you to a more detailed understanding of this knowledge .
2. A step-by-step example
Suppose there is such a simple scenario , stay App Make a request on ,10s Get the response after , Update to the user interface . We may encounter the following expressions .
2.1 Call directly on the main thread

This situation , Everybody knows that , For client development , It is absolutely impossible to perform time-consuming operations on the main thread . In order not to block the main thread , We need to start a new thread , Using callbacks , Send back the results .
2.2 Use callback

This way, , Although it solves the problem of time-consuming operation in the main thread , But it introduces new problems , Update in child thread UI, Will cause the application to crash . To solve this problem , We need to go through the main thread Handler, hold callback post Run to the main thread .
2.3 Use callback and handler Combine

So far, , We use threads , Callback ,Handler combination , A perfect implementation for executing an asynchronous request , And update the results to UI On .
There are three elements in this scheme :
1. Thread or thread pool technology
2. Callback mechanism , Feed the result back to the caller
3. The thread in which the callback operation is executed
So here we should hit the blackboard to draw the key points
Since this article is about cooperative process , So which classes in the collaboration process correspond to these three elements respectively ?
Dispatchers.Main、Dispatchers.IO Equivalent thread
Continuation Corresponding to the callback in the thread
DispatchedContinuation It also specifies Continuation Callback , It also specifies the thread in which the callback is executed .
Let's not start here Continuation and DispatchedContinuation Specific details of , Make a cushion here , I'll explain it in detail later .
2.4 Use a coroutine to implement

This code is the correct code for the coprocessor implementation , There are no time-consuming operations performed by the main thread , No child thread updates UI problem . Of course, there is no explicit callback, And thread switching code . Only right suspendHeavyWork Methods added suspend keyword , You can call asynchronously Using synchronized code . So where is the magic ?
3. Magic uncover
First, post the full version of the code 
Use Android Studio Of Show Kotlin Bytecode Function to view decompiled files 
Sigh with emotion x1 Read the decompiled code , You may need to sigh , There is no time to be quiet , It's just that someone is carrying a load for you . Writing code with coprocessor , Because the compiler did a lot of work later , Understand the work behind this , It is very helpful for us to use the cooperative process .
confused x1 So the code generated by the compiler , Looks familiar and strange , It is said that we are familiar with each line of code in terms of syntax (switch case I'm familiar with them ), I say strange because in general , I don't quite understand what they did , There are even functions ( such as invokeSuspend) I don't even know where to call .
confused x2 What's more confusing is , In the state machine code return sentence , How does the following code execute ? To understand the principle of state machine, we must understand this problem .
4. Research launch Decompile

The top icon shows three important places .
lambda The expression is converted to Function2 example , that Function2 What is it? ? Why did you give me Function2 Passed a type of Continuation Of null object ?
invokeSuspend What is the method ? Note that the parameter is not empty .
call heavyWork(this) Into this object . As we can see from the above ,heavyWork After decompiling, the method becomes heavyWork(Continuation var). It means that Function2 yes Continuation type .
With the above questions , Then the answer is not far away .
4.1 invokeSuspend
First answer the simplest question ,invokeSuspend What is the method . It is defined in BaseContinuationImpl Class , It's an abstract method .


from BaseContinuationImpl(public val completion:Continuation<Any?>?) We can know that the callbacks in the collaboration are linked by a linked list .
Suppose there is suspend The function call is as follows , that Continuation The diagram is as follows .


- First one while loop , It ensures that the state machine can poll .
- val completion = completion!! If at present Continuation There is no callback on the left , Come back quickly
- val outcome = invokeSuspend(param) Call current Continuation Of invokeSuspend Method
- If outcome === COROUTINE_SUSPENDED Go straight back to . That's why delay Method does not block the current thread , encounter suspend Method label Meeting +1, At present Continuation Will pass to delay.
- if (completion is BaseContinuationImpl) Continue to call recursively invokeSuspend
- Otherwise, call completion.resumeWith(outcome) And back to
This code is the core to ensure that the state machine can run .
4.2 Function2 What is it? ?
Function2 yes SuspendLambda, It's defined in ContinuationImpl.kt in . It is BaseContinuationImpl Subclasses of .
5. DispatchedContinuation
internal class DispatchedContinuation<in T>(
@JvmField val dispatcher: CoroutineDispatcher,
@JvmField val continuation: Continuation<T>
)
DispatchedContinuation Yes dispatcher and continuation Two member variables . It means that dispatcher The corresponding thread , perform continuation Callback . When a thread switch occurs , Will certainly generate DispatchedContinuation object , otherwise , After cutting the thread , You can't cut it back .
for example delay and withContext, After switching threads, it will create DispatchedContinuation, To record the thread on which the callback will be called .


Welcome to your attention " Byte station " The official account of the same name !!
Welcome to your attention " Byte station " The official account of the same name !!
Welcome to your attention " Byte station " The official account of the same name !!
边栏推荐
- Comparaison de deux façons d'accéder à la base de données SQL Server (sqldatareader vs sqldataadapter)
- Codeworks 5 questions per day (1700 for each) - the third day
- Interference source current spectrum test of current probe
- C # listbox how to get the selected content (search many invalid articles)
- Axure make menu bar effect
- Esp32 things (V): analysis of common API of esp32 of Swiss Army knife
- Flink Exception -- No ExecutorFactory found to execute the application
- Flink Sql -- toAppendStream doesn‘t support consuming update and delete changes which
- Detectron2 source code reading 3-- encapsulating dataset with mapper
- Use Huawei performance management service to configure the sampling rate on demand
猜你喜欢

基于Svelte3.x桌面端UI组件库Svelte UI

Redis design and Implementation (VI) | cluster (sharding)

Abstract factory pattern

Opencv learning notes -day 11 (split() channel separation function and merge() channel merge function)

Evaluation standard for audio signal quality of intelligent speakers

Redis design and Implementation (V) | sentinel sentry

Opencv learning notes-day14 drawing of image geometry (rect class rotatedrect class, rectangle drawing rectangle circle drawing circular function line drawing line function ellipse drawing elliptic fu

Rew acoustic test (I): microphone calibration

将线程绑定在某个具体的CPU逻辑内核上运行

Wikimedia Foundation announces the first customers of its new commercial product "Wikimedia enterprise"
随机推荐
Rew acoustic test (IV): test principle of rew
[untitled]
Abstract factory pattern
Alcohol tester scheme: what principle does the alcohol tester measure alcohol solubility based on?
Detailed explanation of pipline of mmdetection
Esp32 (7): I2S and I2C drivers for function development
Bottomsheetbehavior principle of realizing the home page effect of Gaode map
Flink Exception -- No ExecutorFactory found to execute the application
Installation, use and explanation of vulnerability scanning tool OpenVAS
Explanation on the use of password profiteering cracking tool Hydra
127.0.0.1, 0.0.0.0 and localhost
Advanced technology management -- how managers design and build echelons
Redis design and Implementation (VI) | cluster (sharding)
Circuit analysis of current probe
Anchorgenerator for mmdet line by line interpretation
127.0.0.1、0.0.0.0和localhost
Invalid update: invalid number of sections. The number of sections contained in the table view after
TiDB 6.0:让 TSO 更高效丨TiDB Book Rush
Esp32 (4): overview of the overall code architecture
Opencv learning notes-day9 opencv's own color table operation (colormap coloraptypes enumeration data types and applycolormap() pseudo color function)