What is written here is some personal understanding of coroutine, if you have any questions, please kindly comment

There are several ways to create coroutines in Kotlin, of which launch and Async are the most common

Without further ado, the simplest way to create coroutines is launch, while async is:

1. Async does not delay operations. If you need to delay operations, you should pass the start parameter CoroutineStart

2. Async is not used for concurrent operations. As long as a coroutine is started in the scope of coroutine, no matter launch or async, it will start to work

While async is the outermost coroutine opening method, the exception is silently discarded and is only thrown when the await() method is called. While an internal coroutine of another coroutine passes an exception to the parent, there is no need to call the await() method

Understanding of the container scope and container job:

1. There are two ways to create or work:

In the coroutine, the container is designed to look like this:

    Scope controls a level of coroutines in my application
val scope = CoroutineScope(Job())
 
 
scope.launch {
    supervisorScope {
        launch {
            // Child 1
        }
        launch {
            // Child 2}}}Copy the code

Or it’s going to be created using the CoroutineScope(container), it’s going to look like this:

class Test : CoroutineScope by CoroutineScope(SupervisorJob() + Dispatchers.IO + CoroutineExceptionHandler { coroutineContext, throwable ->  }) {

    private  val TAG = "Test"

    fun test(){// Here are two coroutines, one of which fails and the other continues to run
        launch(start = CoroutineStart.LAZY) { throw Exception("aaa") }
        launch { Log.i(TAG, "test: ${Thread.currentThread().name}, ${coroutineContext[Job]}")
            for (i in 0.100.){
                delay(1000)
                Log.i(TAG, "doSomething: $i")}}}}Copy the code

In addition to these two types, all other types, whether launch or async, create ordinary jobs

The container is designed to handle anomalies that are passed to the parent when it is used in the container, but it is safe to ensure that other children of the parent are not affected

3. In fact, as long as we do the exception processing of the child launcher and do not let the exception be passed to the parent, it will not affect other child coroutines in the parent

# # # for CoroutineExceptionHandler understand:

1. CoroutineExceptionHandler CoroutineContext is an optional element, it allows you to handle an uncaught exception. Son as long as in the parent configuration CoroutineExceptionHandler, result in abnormal coroutines, will be the parent of CoroutineExceptionHandler captured, like this:

val scope = CoroutineScope(Job())
scope.launch(handler) {
   launch {
       throw Exception("Failed coroutine")}}Copy the code

2. The child the launcher if they want their handle exceptions and not passed, can be used in child coroutines try catch packages, rather than in a configuration CoroutineExceptionHandler coroutines


val scope = CoroutineScope(Job())
scope.launch {
   launch(handler) {
       throw Exception("Failed coroutine")}}Copy the code

The reason exceptions are not caught is because handlers are not installed with the correct CoroutineContext. The internal coroutine propagates an exception as it occurs and passes it to its parent, which is unaware of the handler’s existence and the exception is not thrown.

Reference links:

Blog.csdn.net/jILRvRTrc/a…