Coroutines build upon regular functions by adding two new operations. In addition to invoke (or call) and return, coroutines add suspend and resume.
suspend — pause the execution of the current coroutine, saving all local variables resume — continue a suspended coroutine from the place it was paused
you can only call suspend functions from other suspend functions, or by using a coroutine builder like launch to start a new coroutine. suspend函数只能在suspend函数中调用,或者在coroutine builder中.
To specify where the coroutines should run, Kotlin provides three Dispatchers you can use for thread dispatch:
+-----------------------------------+
| Dispatchers.Main |
+-----------------------------------+
| Main thread on Android, interact |
| with the UI and perform light |
| work |
+-----------------------------------+
| - Calling suspend functions |
| - Call UI functions |
| - Updating LiveData |
+-----------------------------------+
+-----------------------------------+
| Dispatchers.IO |
+-----------------------------------+
| Optimized for disk and network IO |
| off the main thread |
+-----------------------------------+
| - Database* |
| - Reading/writing files |
| - Networking** |
+-----------------------------------+
+-----------------------------------+
| Dispatchers.Default |
+-----------------------------------+
| Optimized for CPU intensive work |
| off the main thread |
+-----------------------------------+
| - Sorting a list |
| - Parsing JSON |
| - DiffUtils |
+-----------------------------------+
你在主线程吊起suspend函数,你的suspend函数中可以指定哪些代码需要跑到其他的Dispathcer中.
// Dispathers.Main
suspend fun fetchDocs(){
val result = get("xxx")
// Dispathers.Main
show(result)
}
//Dispatchers.Main
suspend fun get(url:String) =
// Dispathers.IO
withContext(Dispathcers.IO){
//perform blocking network IO here
}
//Dispatchers.Main
switching between Dispatchers. Default and Dispatchers.IO is optimized to avoid thread switches whenever possible. Kotlin中dispatcher的互相切换不会导致线程上下文切换.
On Android,you can use them to solve two really common problems:
1.Simplifying the code for long running tasks such as reading from the network, disk, or even parsing a large JSON result. 2.Performing precise main-safety to ensure that you never accidentally block the main thread without making code difficult to read and write.
It’s quite difficult to keep track of one thousand coroutines manually using code. You could try to track all of them and manually ensure they complete or cancel, but code like this is tedious and error prone. If the code is not perfect, it will lose track of a coroutine, which is what I call a work leak.
to help avoid leaking coroutines,Kotlin introduced structured concurrency.
On Android, we can use structured concurrency to do three things:
1.Cancel work when it is no longer needed. 2.Keep track of work while it’s running. 3.Signal errors when a coroutine fails.
There are two ways to start coroutines, and they have different uses: launch builder will start a new coroutine that is “fire and forget” — that means it won’t return the result to the caller. async builder will start a new coroutine, and it allows you to return a result with a suspend function called await.
Warning: A big difference between launch and async is how they handle exceptions. async expects that you will eventually call await to get a result (or exception) so it won’t throw exceptions by default. That means if you use async to start a new coroutine it will silently drop exceptions. 除了是否有返回值以外,对异常的处理也很不一样launch和async. async默认是不会抛出异常的.
Structured concurrency guarantees when a scope cancels, all of its coroutines cancel.
On Android, it often makes sense to associate a CoroutineScope with a user screen. This lets you avoid leaking coroutines or doing extra work for Activities or Fragments that are no longer relevant to the user. When the user navigates away from the screen,the CoroutineScope associated with the screen can cancel all work. 关联一个screen和CoroutineScope.这样使得当界面退出后,与之相关的coroutine能及时cancel.
ViewModelScope will automatically cancel any coroutine that is started by this ViewModel when it is cleared (when the onCleared() callback is called).
To use coroutines in a ViewModel, you can use the viewModelScope extension property from lifecycle-viewmodel-ktx:2.1.0-alpha04.viewModelScope is on-track to be released in AndroidX Lifecycle (v2.1.0)
a CoroutineScope will propagate itself. So, if a coroutine you start goes on to start another coroutine, they’ll both end up in the same scope. That means even when libraries that you depend on start a coroutine from your viewModelScope, you’ll have a way to cancel them!
Structured concurrency guarantees that when a suspend function returns, all of its work is done.
the coroutineScope builder will suspend itself until all coroutines started inside of it are complete.
supervisorScope vs. coroutineScope. The main difference is that a coroutineScope will cancel whenever any of its children fail. So, if one network request fails, all of the other requests are cancelled immediately. If instead you want to continue the other requests even when one fails, you can use a supervisorScope. A supervisorScope won’t cancel other children when one of them fails.
来源:oschina
链接:https://my.oschina.net/u/182639/blog/3049356