I’m participating in nuggets Creators Camp # 4, click here to learn more and learn together!
The introduction
In 2022, for an Android developer, if Kotlin is used as the main development language, then coroutines can be said to be essential asynchronous framework. But for beginners, sometimes there are still some comprehension problems or confusion about how to use them. After all the callbacks and threads we’ve been using for years, it does take a process to suddenly change your mind.
This article will be combined with the actual problems encountered by other students, from threads to coroutines, beginners for [synchronization] understanding questions.
background
This happened because in the group this morning, I found that some students asked this question:
Coroutine A: open A wait page and wait until B completes
Coroutine B: communicates with the lower computer and notifies coroutine A of the notify after the lower computer replies successfully
The specific dialog is shown as follows:
Here’s the student’s idea:
Open two coroutines. Coroutine A opens A wait page and waits here. After the execution of coroutine B is successful, coroutine A will be notified to refresh.
By default, coroutines are sync. Suspend directly. Why notice? Isn’t it troublesome?
It’s an easy fix, but my first reaction is, he seems to have misunderstood synchronization in coroutines, right? But on the other hand, on reflection, why can this student have doubts? It seems that I have also asked why I can’t wait for another job to inform me that I have completed it. So I wanted to tell him why?
This is the main chapter of this paper:
In the face of coroutines, how can we change the thread framework or callback idea
The solution
Before I elaborate on the idea, LET me write the following different solutions to give you a better sense of the difference:
1. Thread writing
Define two threads: thread A starts, thread B waits, thread B executes the logic, and thread A notify is called when the logic succeeds.
fun threadTest(a) {
// job A
val jobA = thread(start = false) {
println("Start executing success logic")
}
jobA.wait()
// job B
thread {
Thread.sleep(1000)
jobA.notify()
}
}
Copy the code
2. Interface callback
If a callback is used to avoid blocking the thread, it is written like this again:
Define an interface, task A starts to execute, wait here, wait for the other task B to complete, then call task A interface method to complete the wake up.
fun callBackTest(a) {
val jobA = {
println("Start executing success logic")}/ / jobB began
thread {
Thread.sleep(1000)
jobA.invoke()
}
}
Copy the code
3. Coroutines
parsing
On the Android website, coroutines are described as follows:
Coroutines are a concurrent design pattern that you can use on the Android platform to simplify code that executes asynchronously.
To put it simply, in the world of coroutines, everything is synchronized, in order. Step by step, we wait for the results of the previous step, and then decide whether to proceed to the next step.
By comprehensive comparison of the above solutions:
- Thread writing: we need to call
await
, which would cause running threads to [block], impacting our performance; - Callback writing: We no longer block threads, but our logic is more complex, which increases reading costs if there are multiple callbacks;
- Coroutine writing: We provide two different writing options, namely whether callbacks in the corresponding method need to be improved.
- The former, on task B, we switched to
IO coroutines
, and eventually return the state. Next, we decide that if the state we get is the way we want to write it, we continue; - The latter, on task B, took advantage of
suspendCoroutine
Function, we can change some of the callback code to the synchronous writing of the coroutine to get the same experience as the former;
- The former, on task B, we switched to
Therefore, coroutines have the following basic characteristics:
More lightweight and simplified asynchronous code
When faced with difficult asynchronous code, the first thing to consider is not how to notify, but to see if we can split the task, for example, by breaking the notification step into three steps:
In A non-coroutine world, we might want to execute task A first, wait for task B to succeed, and then tell A to continue.
In the world of coroutines, we can change to: perform the prelude of task A first, then perform task B, and decide whether to continue to perform the subsequent steps of task A according to the results of task B.
extension
The following functions may be helpful for beginners.
suspend
Convert a piece of plain code to a suspend function
suspend {
delay(1000)
withContext(Dispatchers.IO){
}
}
Copy the code
Turn the callback code into a coroutine
suspendCoroutine
// Cancelable suspend function
suspendCoroutine<Int> {
// It is easy to modify some callback operations to synchronous writing
/ / success
it.resumeWith(Result.success(1))
// Exception or failure
it.resumeWith(Result.failure(RuntimeException("Abnormal")))
// For the KTX extension above
// Extend the function for resumewith-success encapsulation
it.resume(1)
// Extend functions to encapsulate resumewith-failure
it.resumeWithException(RuntimeException("Abnormal"))}Copy the code
suspendCancellableCoroutine
Cancel, which supports cancelling the coroutine, will throw a CancellationException.
Afterword.
This article is a relatively simple introduction of an article, but also reply to other students, do a record. While it may seem simple to us, it’s always good to have questions and ask them along the way.
reference
Kotlin coroutine on Android
I’m Petterp, a third-rate developer. If this article helped you, please give it a thumbs up.