即使在 IO 協程上呼叫流,我的以下代碼似乎也阻塞了主執行緒。我是一個 kotlin 和 flow 菜鳥。我在這里做錯了什么阻塞了主執行緒?
存盤庫:
fun observeData(): Flow<Data> {
return flow {
//third party api is getting data from a ContentProvider
ThirdPartyApi.getData().map { convertFromExternalModelToDataModel(it) }
.collect {
emit(it)
}
}
}
視圖模型:
fun updateUI() {
scope.launch(Dispatchers.IO) {
repository.observerData().collect {
withContext(Dispatchers.Main) {
textView.text = data.name
}
}
}
}
運行以下代碼后,我看到來自 Android Choreographer 的日志“跳過 200 幀。應用程式在主執行緒上作業太多”
uj5u.com熱心網友回復:
要在 Kotlin Flows 發出時收集資料流,請使用collect
. 作為collect
一個掛起函式,它需要在協程中執行。它采用 lambda 作為引數,在每個新值上呼叫。由于它是一個掛起函式,呼叫 collect 的協程可能會掛起,直到流程關閉。
而且你不應該在 ViewModel 中更新你的 UI。
在這種情況下,我們在一個活動的生命周期范圍內收集流,該范圍是主要安全的并且具有活動的生命周期意識。
而要使我們的服務或存盤庫在不同的地方執行CouroutineContext
,請使用中間運算子flowOn
。
flowOn
改變CoroutineContext
上游流的 ,意味著生產者和之前(或以上)應用的任何中間運營商flowOn
。
下游流(以及消費者之后的中間運算子flowOn
)不受影響,并在CoroutineContext
用于從流中收集的物件上執行。
視圖模型:
fun getData():Flow<Data> = repository.observeData() // Execute on the io dispatcher
// flowOn affects the upstream flow ↑
.flowOn(Dispatchers.IO)
// the downstream flow ↓ is not affected
.catch { exception -> // Executes in the consumer's context
emit(Data())
}
活動:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch { // Consumer's context
viewModel.getData().collect { // Suspended
textView.text = data.name // Collect on consumer's context
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/469141.html
上一篇:為什么Java多執行緒代碼死鎖