Kotlin (5): Coroutines
kotlin home: https://kotlinlang.org
reference: https://juejin.cn/post/6987724340775108622
仔細看完文件後,發現coroutines並不是那麼簡單,反而使用方法有點複雜.
----
dependencies
{
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:+'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:+'
}
-----
coroutine 典型用法,啟動協程:---
launch並不會等待當前協程的執行結果,所以launch適用於一些不需要等待返回的函數.
button.setOnClickListener {Coroutines不只有一種撰寫方式.其他用法:
setNewText("Click!")
CoroutineScope(IO).launch {
fakeApiRequest()
}
}
fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
// ...
): Job
or
suspend fun main() = coroutineScope { launch { delay(5000) println("Kotlin Coroutines World!") } println("Hello") }
output:
Hello----
or
fun main() { GlobalScope.launch{
// launch a new coroutine in background and continue delay(1000L) // non-blocking delay for 1 second (default time unit is ms) println("World!") // print after delay
}
println("Hello,")
// main thread continues while coroutine is delayed
Thread.sleep(2000L)
// block main thread for 2 seconds to keep JVM alive }
ps: 上面這段程式碼的輸出: 先列印Hello, 延遲1s之後, 列印World.----
來另一個範例:
private fun setNewText(input: String){
val newText = text.text.toString() + "\n$input"
text.text = newText
}
private suspend fun setTextOnMainThread(input: String) {
withContext (Main) {
setNewText(input)
}
}
private suspend fun fakeApiRequest() {
logThread("fakeApiRequest")
val result1 = getResult1FromApi() // wait until job is done
if ( result1.equals("Result #1")) {
setTextOnMainThread("Got $result1")
val result2 = getResult2FromApi() // wait until job is done
if (result2.equals("Result #2")) {
setTextOnMainThread("Got $result2")
} else {
setTextOnMainThread("Couldn't get Result #2")
}
} else {
setTextOnMainThread("Couldn't get Result #1")
}
}
可以很明顯看到,當執行到suspend function. 系統會產生一個全新thread, 在此Function內程式會 block住,不會往下執行. 而同時間另一個執行序:主執行序(UI main thread)會繼續執行.
這邊就有兩個重點了,
withContext (Dispatchers.Main) {
...
}
1. whar is Dispatchers.Main ???
Answer:
To specify where the coroutines should run, Kotlin provides three dispatchers that you can use:
Dispatchers.Main — Use this dispatcher to run a coroutine on the main Android thread. This should be used only for interacting with the UI and performing quick work. Examples include calling suspend functions, running Android UI framework operations, and updating LiveData objects.
Dispatchers.IO — This dispatcher is optimized to perform disk or network I/O outside of the main thread. Examples include using the Room component, reading from or writing to files, and running any network operations.
Dispatchers.Default — This dispatcher is optimized to perform CPU-intensive work outside of the main thread. Example use cases include sorting a list and parsing JSON.
2.withContext():
----
runBlocking: (很少用)
有別於launch和async讓程式碼並聯執行, runBlocking可以建立一個block當前線程的coroutine.------
fun main() =
runBlocking
{ val job = GlobalScope.launch { // launch a new coroutine and keep a reference to its Job delay(1000L) println("World! + ${Thread.currentThread().name}") } println("Hello, + ${Thread.currentThread().name}") job.join() // wait until child coroutine completes }
輸出:
Hello, + main @coroutine#1
World! + DefaultDispatcher-worker-1 @coroutine#2
----
----
suspend:
suspend方法只能在協程或者另一個suspend方法中被調用.
----
fun login(username: String, token: String) { // Create a new coroutine on the UI thread viewModelScope.launch {
val jsonBody = "{ username: \"$username\", token: \"$token\"}" // Make the network call and suspend execution until it finishes val result = loginRepository.makeLoginRequest(jsonBody) // Display result of the network request to the user when (result) { is Result.Success<LoginResponse> -> // Happy path else -> // Show error in UI } } }
我們也可以先等待新的 coroutine 執行結束後再繼續,如下面的程式碼。
fun main() = runBlocking { val job = launch { println("Hello Coroutine!") } job.join() println("Complete") }
launch()
會回傳一個 Job
型態的物件,而這個 Job 就是代表 coroutine 了。之後,呼叫 Job.join()
,當前 runBlocking()
的 coroutine 會被暫停(suspend),等待 job
的 coroutine 執行結束後,再繼續執行。當前的 coroutine 被暫停後會釋放當前的 thread,所以當前的 thread 可以去執行其他的 coroutine。
----
留言
張貼留言