preface
Hello everyone, I’m Xiao Yi! In the previous chapter, we had a brief understanding of what coroutines are and the basic use of coroutines, mainly mentioning the use of launch and withContext. But launch and withContext are not suitable for concurrent scenarios where results need to be returned, where we typically use coroutines async/await.
recommended
This article will be first published on the public account “Code Man” and personal blog “Li Yi’s small station”. If you think this article is helpful to you, please pay attention to the public account! This article will be first published on the public account “Code Man” and personal blog “Li Yi’s small station”. If this article is helpful to you, please pay attention to the public account!
I. Async and AWIAT
Async refers to asynchrony in its literal sense. Async is also an extension function of CoroutineScope, its source code is as follows:
public fun <T> CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T> {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyDeferredCoroutine(newContext, block) else
DeferredCoroutine<T>(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
Copy the code
Async, like Launch, creates a new coroutine, but Launch returns Job while Async returns Deferred (a subclass of Job). Here is a quick example of how async can be used:
coroutineScope.launch(Dispatchers.IO) {
val a = async{ getUserInfo() }
// Execute the coroutine
val userInfo = a.await()
}
Copy the code
Val a = async{getUserInfo()} does not actually execute getUserInfo(), but returns a Deferred object named A. A.await () is the real start to execute the coroutine so that getUserInfo() gets executed and returns userInfo (**await() the data type returned depends on the type returned by async{}** last line). So it can be concluded that async is just creating and await is executing. In addition, async can also specify a running thread:
val a = async(Dispatchers.IO){ getUserInfo() }
Copy the code
Second, the concurrent
After learning the basic usage of async/await, let’s talk about using async/await to do concurrency, again with a small example!
1. Case 1
coroutineScope.launch(Dispatchers.IO) {
val a1 = async{ getUserInfo() }
val userInfo = a1.await()
val a2 = async{ getMessage(userInfo.token) }
val msgList = a2.await()
}
Copy the code
In case 1, getUserInfo() is executed first, and getMessage() is executed after getUserInfo(), in order.
2. Case 2
coroutineScope.launch(Dispatchers.IO) {
val a1 = async{ getUserInfo() }
val a2 = async{ getHomeInfo() }
val userInfo = a1.await()
val homeInfo = a2.await()
}
Copy the code
In case 2, getUserInfo() and getHomeInfo() are executed concurrently. Here may have a homecoming doubt, why not a1. Await execution again after a2 () has been completed. Await (), such cases and not simply a contradiction? Await () function has a property that, when await() is executed, it will not only execute its corresponding async, it will cause all previous async to execute. Remember this property.
In case 2, a1.await() is a fuse, the execution of a1.await() causes async{getUserInfo()} and async{getHomeInfo()}, which were not executed previously, to start executing. A2.await () is just to getHomeInfo and does not perform async{getHomeInfo()}. To be more rude, getHomeInfo() in case 2 will be executed even without val homeInfo = a2.await(). In case 1, async -> await -> async -> await is used, so only one async will be executed at a time, in order.
Third, suspend
Suspend literally means to suspend and pause, and is used primarily in coroutines to modify functions. It also does what it literally does, suspending the function. The flow can be understood as follows: the coroutine encounters a function marked suspend while executing, and the function is switched to another thread. The execution of the code is in the function that is switched out, so the coroutine code behind the function is not executed. When this function is finished, the coroutine is switched back to the original thread, code execution is reverted to the original thread, and the coroutine code after this function is continued.
To get a clear view of suspend, let’s use a small example:
fun init(a) {
coroutineScope.launch {
val userInfo = getUserInfo()
tv_name.text = userInfo.name
}
}
// Request user information
suspend fun getUserInfo(a): UserInfo {
returnwithContext(Dispatchers.IO){ ... }}Copy the code
In the above example, init has a coroutine that requests user information using getUserInfo(), using the suspend modifier. When the getUserInfo() method is executed, the execution of getUserInfo() is switched from the main thread to the IO thread. The current code execution is suspended on the getUserInfo() method, tv_name.text = userinfo.name, until the getUserInfo() method completes, and the code execution is suspended from the IO thread back to the main thread. Tv_name. Text = userinfo. name Continue.
In fact, if you look at the source code, you’ll see that many methods like withContext are suspend, which is why you can use them to code synchronously.
public suspend fun <T> withContext(
context: CoroutineContext,
block: suspend CoroutineScope.() -> T
): T = suspendCoroutineUninterceptedOrReturn sc@ { uCont ->
...
}
Copy the code
In addition, two points in particular are proposed here:
suspend
It’s just a flag to remind the coroutine to do something about it. The actual thread switching is done by the coroutine itself, not by the coroutinesuspend
The ability to modify the function itselfsuspend
Modified functions can be held by otherssuspend
Function calls, but ultimately thesesuspend
Call execution can only be done in coroutines and cannot be used in isolation like normal methods
Four, summary
So far, we have used two chapters to cover the basic use of coroutines. The next chapter will cover encapsulation of coroutines in MVVM. If you still have questions about the basics of coroutines, check out the documentation for coroutines.
Five, good articles recommended
- “Take a hard look at Kotlin’s Coroutines – Can’t Learn coroutines? Probably because all the tutorials you read are wrong.”
- “Kotlin coroutine hanging so weird and confusing? I skinned it today.”
- What is a “non-blocking” hang, and Are Coroutines Really Lighter?