為了今天要用 async
執行非同步取得咖啡廳資料,所以昨天先做了簡單的實驗,現在直接來改寫程式碼吧~~
binding.button.setOnClickListener {
// 這個 Scope 即是在 Android Main Thread 上啟動 coroutine
lifecycleScope.launch(Dispatchers.Main) {
try {
binding.progressbar.visibility = View.VISIBLE
// 等待非同步執行結果
val deferredResult = fetchCoffeeShopDataByAsync().await()
// 更新畫面
binding.textView.text = deferredResult
binding.progressbar.visibility = View.GONE
}
catch (e: CoffeeShopsRefreshError) {
binding.textView.text = "Request failed \nmessage: ${e.message}"
binding.progressbar.visibility = View.GONE
}
}
}
接著來看看使用 async
在 IO 執行緒上啟動 coroutine
執行非同步任務 fetchCoffeeShopDataByAsync()
:
private fun fetchCoffeeShopDataByAsync(): Deferred<String?> {
return lifecycleScope.async(Dispatchers.IO) {
// 創建一個 OkHttpClient 實例
val client = OkHttpClient()
// 設置要發送的 HTTP 請求
val request = Request.Builder()
.url("http://cafenomad.tw/api/v1.2/cafes/taipei")
.build()
val response = try {
// 使用 OkHttpClient 發送同步請求
client.newCall(request).execute()
}
catch (cause: IOException) {
throw CoffeeShopsRefreshError("Unable to refresh data", cause)
}
if (!response.isSuccessful) {
throw CoffeeShopsRefreshError("Unable to refresh data", null)
}
return@async response.body?.string()
}
}
重點只有兩點 :
lifecycleScope.async(Dispatchers.IO) {}
: 在 IO 執行緒上啟動 coroutine
return@async response.body?.string()
return@async
是用來指定要返回的值,因為目前還沒把 Json 字串接出來,就簡單地返回字串就好。
終於成功拉~~~
好好讀完後再寫就沒有感到很難,學習果然不能囫圇吞棗阿哈哈