Coroutines, full name can be translated coroutines, many languages have this concept and the concrete implementation, before contact with introduction to Python, and Kotlin actually has the extension function library, also just had been at the experimental stage, but recently a formal version 1.0 is finally out, from the blog on the net also more up, After these days of learning I also do a summary.

Environment configuration

Kotlinx. coroutines is the official github address of Kotlin coroutines. The following configuration is based on the instructions here, and there are also many basic examples for us to prepare, interested friends can go to see later.

First configure the Kotlin version

buildscript {
    ext.kotlin_version = '1.3.11'
}
Copy the code

Dependencies are then introduced, and the latest version is 1.1.0

   implementation 'org. Jetbrains. Kotlinx: kotlinx coroutines -- core: 1.1.0'
   implementation 'org. Jetbrains. Kotlinx: kotlinx coroutines - android: 1.1.0'
Copy the code

Configuration is simple, so what happens next. Write a coroutine version of Hello World, of course!

import kotlinx.coroutines.*

fun main() {globalscope.launch {// Create and start a coroutine delay(1000L) // delay(suspend) 1000ms, note that this does not block the thread println()"World!"} println()"Hello,"Sleep (2000L); // Block the Thread for 2s to ensure that the JVM is alive and the coroutine can complete normally}Copy the code

Running results:

The 2018-12-23 17:35:16. 998, 15539-15539 / com. Renny. Kotlin I/System. Out: Hello, 2018-12-23 17:35:18.005 15539-18893/com.renny.kotlin I/ system. out: World!Copy the code

Basic grammar

Boot mode

The above coroutine start mode is the default DEAFAULT, which means it is created and started immediately. We can also set the start mode to LAZY, which allows us to specify when it needs to start.

fun main(a) {
        val job = GlobalScope.launch(start = CoroutineStart.LAZY) {
            println("World!")
        }
        println("Hello,")
        job.start()
        Thread.sleep(2000L)
    }
Copy the code

In the Kotlin 1.3 version I used, there are two additional modes, ATOMIC and UNDISPATCHED, but they are experimental and not covered here. The result is as follows. The coroutinescope.launch has three parameters:

  • context: CoroutineContext = EmptyCoroutineContext: Coroutine context
  • block: suspend CoroutineScope.() -> Unit: closure parameter that defines the operations to be performed within the coroutine.

The return value is a Job object.

Job class

The main thing to see from the above example is that the launch function returns a value, which is an interface type of Job. In addition to starting a coroutine with LAZY, here are some other important methods:

  • job.cancel()Cancel a coroutine
    fun main() {
        val job = GlobalScope.launch {
            delay(1000L)
            println("World!")
        }
        job.cancel()
        println("Hello,")}Copy the code

The coroutine is canceled, so it just prints Hello,

  • join()Wait for the coroutine to finish executing
fun main(a) = runBlocking {
    val job = GlobalScope.launch {
        delay(1000L)
        println("World!")
        delay(1000L)
    }
    println("Hello,")
    job.join() 
    println("Good!")}Copy the code

Much like thread.join (), the code after join() waits until the coroutine ends, resulting in the following:

The 2018-12-24 21:19:41. 153, 23484-23484 / com. Renny. Kotlin I/System. Out: Hello, 2018-12-24 21:19:42.148 23484-24172/com.renny.kotlin I/ system.out: World! 2018-12-24 21:19:43.161 23484-23484/com.renny.kotlin I/ system.out: Good!Copy the code
  • job.cancelAndJoin()Wait for the coroutine to complete and then cancel this is oneJobExtension function, which combines thecanceljoinTo see its implementation:
public suspend fun Job.cancelAndJoin(a) {
    cancel()
    return join()
}
Copy the code

Hang up function

Job.join() is blocked by a blocking function called runBlocking, but job.start () and job.cancel are not blocked. Job.cancelandjoin () is preceded by a special keyword suspend.

Job.join() is also decorated by suspend, so it is a suspend function. The suspend function must be used either in the coroutine or in the suspend function, because job.join () is called, Job.cancelandjoin () must also be accompanied by the suspend statement. In fact, to start a coroutine, you must have at least one suspend function.

Coroutine and coroutine suspend:

Coroutines are implemented by compilation technology, do not require the support of the VIRTUAL machine VM/ operating system OS, through the relevant code to take effect coroutines suspend almost no cost, no context switch or involving OS coroutines can not be suspended in random instructions, only suspended at the point of suspension (call tag function)!Copy the code

The child coroutines

We started one coroutine in a thread, and we can start another coroutine in a thread, so let’s look at a more complicated example:

 fun main(a) = runBlocking {
        GlobalScope.launch {
            delay(1000L)
            println("World!")
        }
        println("Hello,") 
        runBlocking {     
            delay(2000L)  
        }
    }
Copy the code

The outermost runBlocking is the highest level of the coroutine (usually the main coroutine), and other coroutines such as launch {} can run in the runBlocking because of their lower level. The biggest feature of runBlocking is that its delay() can block the current Thread in the same way that thread.sleep () does. The printed log is the same as in the first example.

A collection of subcoroutines stored in the Job class:

public val children: Sequence<Job>
Copy the code

It also provides a way to cancel all subcoroutines:

public fun Job.cancelChildren(a) {
    children.forEach { it.cancel() }
}
Copy the code

summary

This article mainly introduces the configuration of the introduction of coroutines into the Android project, some basic operations of coroutines, the concept of suspended functions, we have a basic concept of coroutines, the next chapter will talk about more knowledge of coroutines.

Refer to the article

Kotlin coroutine official documentation