This article covers some of the basics of Kotlin coroutines
1. Suspend the keyword
We know the point of coroutines when you suspend a function, and many of you know the suspend function, which is suspend and resume. But t why and how can suspend and resume functions?
From a Java perspective
- 1. I define the suspend function and a normal function in Kotlin, and neither of them returns a value.
- 2. After decompilation, it can be seen that with
suspend
Keyword function, he needs to pass in oneContinuation
Object and the return type isobject
. The ordinary function is stillvoid
Question one, what is a Continuation?
Let’s start with a question: When we operate on something, we usually get information about it and make a judgment about it, so where is information about a suspended function stored? With that in mind we turn to continuations
-
1. A Continuation is an interface that contains a context and a resumeWith method. (Note: resumeWith = resume + resumeWithException)
-
2. Normally a context is a data set, and this is no exception, so all of our information can be stored and retrieved there
-
3. ResumeWith passes a successful or failed method, which is equivalent to a callback
Question two, where does the Continuation come from?
Before that, why can a suspended function be called only from another suspended function or coroutine?
-
In Kotlin, the compiler passes in a Continuation object, so we don’t need to pass it in a method, but where does the compiler come from for a Continuation object? Let’s look at the above question again, do you understand anything?
-
2. As a side note, Kotlin uses the system-provided suspendCoroutine method to retrieve the Continuation object of the current suspended function
Question three, why does Kotlin return no value, but Java returns Object?
1. We know that calling a suspended function does not necessarily mean that the function will be suspended. But if the suspension function is actually suspended it will return a suspended flag COROUTINE_SUSPENDED, so you don’t know what will be returned. If the suspension is no different than a normal function, it can return a String or other type. 2. As a footnote, true suspension requires thread cutting
2. How to create a coroutine
By looking at the source code, I finally found the following two methods
You can see that both methods pass in a Continuation object and then return a new Continuation object
Question one: What are the functions of the two continuations
1. The Continuation that is passed in is given to a call back to completion, so that you can call resumeWith to return the result
2. The returned Continuation, which I think of as the real carrier of the coroutine, can also be thought of as the object that starts the coroutine. Because we can see that in the startContinuatine method, resume is called. And the resume method is in a Continuation. So IN my opinion, for a coroutine to start, resume is used. So a Resume object is returned
Question two, how do I create coroutines in a native way
From the source code creation method can be seen, to create a coroutine, only needSuspend function
.A Continuation object
.A context CoroutineContext data set that stores coroutine information
That’s it, so I just created it
3. The interceptor
- 1. Coroutines also have interceptors. Through searching source code, I found a familiar word when creating them.
intercepted
- 2. After some searching, we found the implementation of this method
ContinuationImpl
- 3. You can see the source code in the context, CoroutineContext, which is a data set, to find
ContinuationInterceptor
The interceptor. And return one at the endContinuation
object
- 4 follow the source code into view
ContinuationInterceptor
Finding her is a realizationCoroutineContext.Element
Class, that is, can be stored as an element inCoroutineContext
Context.
Problem number one, if we write an inheritance ourselvesContinuationInterceptor
Class, can also do interception effect?
- 1. Write a Log blocker! And when I write it out, I find
interceptContinuation
How to implement the method? But we can tell from the return value that he’s going to return oneContinuation
The object’s
- 2. The source code is also relying on this method to return
Continuation
The object’s
- 3. So let’s write another class inheritance
Continuation
It’s all right, then
- It seems to be right, let’s try to prove it. But how do you use it
We know the interceptor isCoroutineContext.Element
Then it can be saved in CoroutineContext. Create an empty CoroutineContext at thread creation time and then add it.
Question two, at what stage does the interceptor help us intercept and process?
- 1. Interception
The resumeWith method for continuations used by suspend
.
- 2. The output of this code looks like this. You can see that the log statement in the log interceptor is printed before the output.
#### Q3, what about adding multiple interceptors? My experiments show that adding multiple interceptors only works for one, because the interceptor Key is singleton.
4. The scheduler
The scheduler allows us to use asynchronous methods as if we were using synchronous code when using coroutines. One of them is that the scheduler does the thread switching for us.
1. So how did he cut the thread for us after the asynchronous request was completed? 2. Considering the above interceptor ideas, we might as well make an interceptor and let it switch threads before executing the suspend closure. 3. I created a new thread in the original Log interceptor to execute these two lines of code and compared the output 4. As you can see, the code that was executed on the main thread has been switched to the Thread0 thread
So I followed the source code to find the source code to add thread scheduling
- 1. It turns out,
The scheduler Dispatch
Also achievedThe interceptor
And he is oneCoroutineContext
The elements of the - 2. So we can see that the scheduler can also add directly to the incoming context
Question 1: Scheduler can help us schedule both startup and recovery. Where is it called?
1. Through my continuous debugging, I found the following two methods. As you can see at a glance, he made the judgment that it is time to schedule the switch thread in both startup and reply. 2. ResumeCancellableWith: start a coroutine
The last
1. I feel that I have not said everything completely. I don’t know how to express something and I still need to add something
2. What is the difference between coroutines and thread pools? Can you think of coroutines as Kotlin’s thread pool
3. If you have any comments or suggestions, please let us know!