假設我有一些需要傳輸到 UI 的資料,并且資料應該以一定的延遲發出,所以我的 ViewModel 中有一個 Flow:
val myFlow = flow {
listOfSomeData.forEachIndexed { index, data ->
//....
emit(data.UIdata)
delay(data.requiredDelay)
}
}
收集并顯示 UI 流中的某處:
@Composable
fun MyUI(viewModel: ViewModel) {
val data by viewModel.myFlow.collectAsState(INITIAL_DATA)
//....
}
現在我希望用戶能夠通過按下某個按鈕來暫停/恢復發射。我怎樣才能做到這一點?
我唯一能想到的是 Flow builder 中的無限回圈:
val pause = mutableStateOf(false)
//....
val myFlow = flow {
listOfSomeData.forEachIndexed { index, data ->
emit(data.UIdata)
delay(data.requiredDelay)
while (pause.value) { delay(100) } //looks ugly
}
}
還有其他更合適的方式嗎?
uj5u.com熱心網友回復:
您可以通過使用流程來保持暫停值然后收集它來整理您的方法:
val pause = MutableStateFlow(false)
//....
val myFlow = flow {
listOfSomeData.forEachIndexed { index, data ->
emit(data.UIdata)
delay(data.requiredDelay)
if (pause.value) pause.first { isPaused -> !isPaused } // suspends
}
}
你需要 mutableStateOf 來撰寫嗎?也許您可以將其轉換為流,但我不知道它看起來如何,因為我不使用 compose。
下面有點創意的咆哮:
我實際上對此感到疑惑并尋找更靈活的方法 - 理想情況下,源流應該在emit. 我注意到它可以在使用緩沖流時完成,BufferOverflow.SUSPEND所以我開始擺弄它。
我想出了這樣的東西,可以讓我暫停任何生產者:
// assume source flow can't be accessed
val sourceFlow = flow {
listOfSomeData.forEachIndexed { index, data ->
emit(data.UIdata)
delay(data.requiredDelay)
}
}
val pause = MutableStateFlow(false)
val myFlow = sourceFlow
.buffer(Channel.RENDEZVOUS, BufferOverflow.SUSPEND)
.transform {
if (pause.value) pause.first { isPaused -> !isPaused }
emit(it)
}
.buffer()
對我來說,這似乎是一個小技巧,并且有一個缺點,即源流在暫停后仍會到達下一個發出呼叫,因此:n值在內部暫停,transform但源在n 1.
如果有人對如何“立即”暫停源流有更好的想法,我很樂意聽到。
uj5u.com熱心網友回復:
如果您不需要特定的延遲,您可以使用flow.filter{pause.value != true}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/443735.html
下一篇:Kotlin:用回圈重復影片x次
