preface
In the process of using coroutines, there are several different functions that start coroutines, each suitable for different scenarios. It mainly includes withContext, launch and async. This article mainly looks at the differences of these several coroutine start functions through an example. Each function has its usage scenarios, and you can choose which function to use according to the goal to be achieved.
launch
Lauch is the most common way to start a coroutine. You can start a global lifecycle coroutine with GlobalScope.Launch. You can also launch a coroutine in the specified CoroutneContext range via the CoroutineScope(CoroutineContext).launch. You can also log the Job and cancel it at any time with job.cancel (). Let’s start with the following example:
fun main(args: Array<String>) {
println("main")
testLaunch()
Thread.sleep(2000)}fun testLaunch(a) {
GlobalScope.launch {
func1()
}
GlobalScope.launch {
func2()
}
}
suspend fun func1(a) {
delay(1500)
println("func1")}suspend fun func2(a) {
delay(300)
println("func2")}Copy the code
In the example above, func2 executes faster than Func1, so let’s see the order of the two functions by starting two coroutines. Using launch does not block the main thread, but because launch is not a suspend function, it does not wait for the coroutine to return.
Output:
before
func2
func1
after
Copy the code
As you can see from the output, launch does not wait for the execution result of the current coroutine, so launch is suitable for functions that do not need to wait for a return, or can perform some actions when the result is obtained by way of a callback.
withContext
Next look at withContext. Replace the above example with withContext to see how launch differs from launch:
fun testWithContext(a) {
GlobalScope.launch {
func1WithContext()
func2WithContext()
}
}
suspend fun func1WithContext(a) = withContext(Dispatchers.IO) {
delay(1500)
println("func1")}suspend fun func2WithContext(a) = withContext(Dispatchers.IO) {
delay(300)
println("func2")}Copy the code
Output:
before
func1
func2
after
Copy the code
As you can see from the output, func1WithContext and func2WithContext are executed sequentially. Since withContext is the suspend function, the coroutine is suspended at this point until the function completes. WithContext requires passing in a scheduler parameter specifying which thread the coroutine is running on.
As you can see, you can use withContext when you need to wait for the result of a function, and the withContext waits for the result to return and doesn’t block the main thread. But there is a problem here. If there are multiple time-consuming tasks in the same coroutine, but there is no logical relationship between them, then using withContext makes all tasks serial inefficient. Is there a way to perform multiple tasks in parallel, but wait for all the tasks to return? Take a look at async below.
async:
Let’s change the example to use async to see the result of the execution, simply modify the function, each return a value, and finally calculate the sum of the return values of the two functions:
fun testAsync(a) {
GlobalScope.launch {
val deferred1 = async(Dispatchers.IO) { func1Async() }
val deferred2 = async(Dispatchers.IO){ func2Async() }
val result = deferred1.await() + deferred2.await()
println("the sum is: $result")}}suspend fun func1Async(a): Int {
delay(1500)
println("func1")
return 1
}
suspend fun func2Async(a): Int {
delay(300)
println("func2")
return 2
}
Copy the code
Output:
before
func2
func1
the sum is: 3
after
Copy the code
As you can see from the output above, func2Async executes faster than func1Async, indicating that the two functions are parallel. But the end result is correct, and that’s what async does. You can see async returns Deferred
. Deferred
represents a non-blocking class cancellation value inherited from Job. * * look at the final use case to deferred1. Await () + deferred2. Await (), it means the values that you need to wait for two async return will perform, * * which await () is actually a suspend function. ** Async and launch have the same effect when not using await(). Another thing to note is when to call await, if the above example is changed to:
val deferred1 = async(Dispatchers.IO) { func1Async() }.await()
val deferred2 = async(Dispatchers.IO){ func2Async() }.await()
val result = deferred1 + deferred2
Copy the code
If you call it like this it’s going to do the same thing as withContext. The coroutine blocks until func1Async() is complete before func2Async() is executed.
As you can see, Async is suitable for multiple parallel tasks that need to wait for results.
conclusion
- launch
- Does not block until the result is returned
- Doesn’t block the thread
- Parallel execution
- withContext:
- Blocks the current coroutine until the function returns
- Execute functions from the specified Dispatcher
- The thread is not blocked when executing the function
- The serial execution
- async
- When using
awiat
Function, blocks until the result is returned - If you do not use await, it has the same effect as launch
- Suitable for multiple parallel tasks that need to wait for results to return
- Parallel execution
- When using
By the way, ape tutoring R & D recruitment positions, there are a lot of HC. If you are interested, please send your resume to my email: [email protected]. Welcome to 😜 😜