經友人 L 建議,可以透過 LifecycleScope
管理 coroutine
的生命週期。因為在此 LifecycleScope
範圍內的 coroutine
都會在 Lifecycle
被銷毀時自動取消。
在 Gradle(Module)內加入 :
androidx.lifecycle:lifecycle-runtime-ktx:2.4.0
將 CoroutineScope(Dispatchers.Main).launch {}
修改為用 LifecycleScope.launch {}
啟動 coroutine
:
// 原始程式碼
CoroutineScope(Dispatchers.Main).launch {
}
// 修改後
lifecycleScope.launch(Dispatchers.Main) {
try {
binding.progressbar.visibility = View.VISIBLE
fetchCoffeeShopData()
}
catch (e: CoffeeShopsRefreshError) {
binding.progressbar.visibility = View.INVISIBLE
binding.textView.text = "Request failed \nmessage: ${e.message}"
}
}
修改好啦~執行起來也一切正常!
點擊按鈕後執行 refreshText()
來測試使用 async
啟動執行緒 :
// TODO: test async
binding.button.setOnClickListener {
refreshText()
}
運作的流程大概是這樣 :
coroutine
async(Dispatchers.IO)
在 IO 執行緒啟動 coroutine
執行非同步任務,這邊透過 delay(1000)
模擬非同步情形並回傳 Deferred<String>
,使用變數 rawText
儲存回傳結果await()
等待非同步的執行結果,取到後使用變數 deferredResult
儲存非同步結果private fun refreshText() {
lifecycleScope.launch(Dispatchers.Main) {
binding.progressbar.visibility = View.VISIBLE
// 非同步執行取得 "async result"
val rawText: Deferred<String> = lifecycleScope.async(Dispatchers.IO) {
delay(1000)
"async result"
}
// 等待非同步執行結果
val deferredResult = rawText.await()
// 更新
binding.textView.text = deferredResult
binding.progressbar.visibility = View.GONE
}
}
我們成功拉~~~
看來方向沒有錯,接著在試著將取得非同步文字那段程式碼寫成方法提出去。
先看一眼 Kotlin 的方法要怎麼寫 :
要回傳的型別寫在冒號後面,看習慣 Java 的我只覺得眼睛業障重…
來改寫吧,因為未來是用呼叫 API 的方式來取得非同步結果,先從簡單的開始練習 :
// 待修改的程式碼
val rawText: Deferred<String> = lifecycleScope.async(Dispatchers.IO) {
delay(1000)
"async result"
}
加入 getAsyncText()
:
/**
* 非同步執行取得 "async result"
*/
private suspend fun getAsyncText(): Deferred<String> {
return lifecycleScope.async(Dispatchers.IO) {
delay(1000)
"async result"
}
}
refreshText()
:
// 修改後
private fun refreshText() {
lifecycleScope.launch(Dispatchers.Main) {
binding.progressbar.visibility = View.VISIBLE
// 等待非同步執行結果
val deferredResult = getAsyncText().await()
// 更新
binding.textView.text = deferredResult
binding.progressbar.visibility = View.GONE
}
}
再次成功了~~~
每天都寫個一小點,慢慢地就會完成專案了吧~~~
目前進度有點落後呀