Simple application of Kotlin coroutine

Example one:

GlobalScope. launch(Dispatchers. Main) {
    //Start the child coroutine
    withContext(Dispatchers.IO) {
        for (i in 0 until 1000) {
        }
        Log.d("MainActivityXX", "withContext-> thread:" + Thread.currentThread().name)
    }
    Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name)
}
Log.d("MainActivityXX", "onCreate-> thread:" + Thread.currentThread().name)

print log:

2022-10-09 20:24:21.100 8371-8371/com.example.xiecheng D/MainActivityXX: onCreate-> thread:main
2022-10-09 20:24:21.131 8371-8412/com.example.xiecheng D/MainActivityXX: withContext->thread:DefaultDispatcher-worker-1
2022-10-09 20:24:21.258 8371-8371/com.example.xiecheng D/MainActivityXX: GlobalScope-> thread:main

Example two:

GlobalScope. launch(Dispatchers. Main) {
    //Start the child coroutine
    withContext(Dispatchers.IO) {
        for (i in 0 until 1000) {
        }
        Log.d("MainActivityXX", "withContext1-> thread:" + Thread.currentThread().name)
        withContext(Dispatchers.IO) {
            for (i in 0 until 1000) {
            }
            Log.d("MainActivityXX", "withContext2-> thread:" + Thread.currentThread().name)
        }
    }
    withContext(Dispatchers.IO) {
        for (i in 0 until 1000) {
        }
        Log.d("MainActivityXX", "withContext3-> thread:" + Thread.currentThread().name)
    }
    Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name)
}
Log.d("MainActivityXX", "onCreate-> thread:" + Thread.currentThread().name)

print log:

onCreate->thread:main
withContext1\->thread:DefaultDispatcher-worker-1
withContext2\->thread:DefaultDispatcher-worker-1
withContext3\->thread:DefaultDispatcher-worker-1
GlobalScope\->thread:main

The main thread starts a coroutine, which will not hinder the execution of the main thread. A single coroutine is executed serially, and the whole one here is executed serially because withContext is a suspending function.

GlobalScope. launch(Dispatchers. Main) {
    //Start the child coroutine
    GlobalScope. launch(Dispatchers.IO) {
        Log.d("MainActivityXX", "withContext-> thread:" + Thread.currentThread().name)
    }
    Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name)
}

print log:

GlobalScope-> thread:main
withContext\->thread:DefaultDispatcher-worker-1

Example two:

GlobalScope. launch(Dispatchers. Main) {
    //Start the child coroutine
    withContext(Dispatchers.IO) {
        get()
        Log.d("MainActivityXX", "withContext-> thread:" + Thread.currentThread().name)
    }
    Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name)
}
suspend fun get() {
    Thread {
        Thread. sleep(5000)
        Log.d("MainActivityXX", "get-> thread:" + Thread.currentThread().name)
    }.start()
}

print log:

2022-11-01 20:56:25.220 20058-20100/com.example.xiecheng D/MainActivityXX: withContext-> thread:DefaultDispatcher-worker-1
2022-11-01 20:56:25.264 20058-20058/com.example.xiecheng D/MainActivityXX: GlobalScope-> thread:main
2022-11-01 20:56:30.222 20058-20103/com.example.xiecheng D/MainActivityXX: get-> thread:Thread-8

If the thread is enabled in the coroutine, the thread will not be affected by the coroutine.

Example three:

GlobalScope. launch(Dispatchers. Main) {
    fetchDocs()
}

suspend fun fetchDocs() { // Dispatchers. Main
    val result = get("https://developer.android.com") // Dispatchers.IO for \`get\`
    Log.d("MainActivityXX", "fetchDocs-> thread:" + Thread.currentThread().name)
}
//withContext itself is a suspending function
suspend fun get(url: String) = withContext (Dispatchers.IO) {
    Log.d("MainActivityXX", "get-> thread:" + Thread.currentThread().name)
}

print log:

get->thread:DefaultDispatcher-worker-1
fetchDocs\->thread:main

If the suspend function is used, it will wait for the get method to be executed before performing the following operations.

1. The suspending function will not block the thread where it is located, which greatly improves the concurrency flexibility of the thread and maximizes the utilization efficiency of the thread.
When CoroutineA running on ThreadA calls the delay(1000L) function to specify a delay of one second before running, ThreadA will turn to execute CoroutineB, and then continue to execute CoroutineA after one second

2. withContext itself is a suspending function.

3. The suspended object is a coroutine.

4. The suspend keyword, since it does not really implement suspension, it is actually a reminder. The creator of the function reminds the user of the function: I am a time-consuming function, and I am put in the background by my creator in a suspended manner, so please call me in the coroutine.
Why does the suspend keyword not actually operate the suspension, but Kotlin provides it?
Because it is not used to operate the hang. Suspended operations-that is, thread cutting-rely on the actual code in the suspending function, not on this keyword.
So this keyword, is just a reminder.
Therefore, to create a suspend function, in order to make it contain the real suspend logic, you must directly or indirectly call the suspend function that comes with Kotlin inside it, and your suspend is meaningful.

5. So this suspend does not actually play the role of suspending any coroutines, or switching threads. It is Kotlin’s coroutine framework that does it for us to actually suspend the coroutine.
So we want to write a suspend function by ourselves. It is not enough to just add the suspend keyword. It is also necessary to directly or indirectly call the suspend function that comes with the Kotlin coroutine framework inside the function.

6. Developers need to understand that coroutines run on threads, and one thread can run multiple (could be tens of thousands) coroutines. The scheduling behavior of threads is manipulated by the OS, while the scheduling behavior of coroutines can be specified by the developer and implemented by the compiler. When coroutine A calls the delay(1000L) function to specify a delay of 1 second before running, the thread where coroutine A is located will just turn to execute coroutine B, and wait until 1 second before adding coroutine A to the schedulable queue inside. Therefore, the thread will not be blocked due to the delay of the coroutine, which can greatly improve the concurrency flexibility of the thread.

A new start

There is no shortcut to change your life. This road needs to be walked by yourself. Only by thinking deeply, constantly reflecting and summarizing, maintaining the enthusiasm for learning, and building a complete knowledge system step by step, is the ultimate way to win. It is also the mission that programmers should undertake.

If you need advanced Android senior engineer system learning materials, I can share them with you for free. Friends who need the full version, [Scan the QR code]

Learning Video Series

“Study Document Series”

“My Dachang Interview Journey”