Nis*_*lan 7 android kotlin kotlin-coroutines kotlin-flow kotlin-sharedflow
在我的 ViewModel 中,我正在发出 API 请求,并且正在使用 FragmentStateFlow并SharedFlow与 Fragment 进行通信。在发出 API 请求时,我可以轻松更新状态流的值,并将其成功收集到片段中。
但在发出请求之前,我发出了一些布尔值,SharedFlow并且它没有被收集在片段中。有人可以帮助我为什么会发生这种情况吗?
class MainViewModel: ViewModel() {
private val _stateFlow = MutableStateFlow(emptyList<Model>())
val stateFlow = _stateFlow.asStateFlow()
private val _loading = MutableSharedFlow<Boolean>()
val loading = _loading.asSharedFlow()
suspend fun request() {
_loading.emit(true)
withContext(Dispatchers.IO) {
/* makes API request */
/* updates _stateFlow.value */
/* stateFlow value is successfully collected */
}
_loading.emit(false) // emitting boolean value
}
}
Run Code Online (Sandbox Code Playgroud)
class MyFragment : Fragment(R.layout.fragment_my) {
// ...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
lifecycleScope.launchWhenStarted {
viewModel.request()
/* stateFlow is collected and triggered - working properly */
viewModel.loading.collectLatest { // <- NOT COLLECTING - WHY?
Log.d(this::class.simpleName, "onViewCreated: $it") // <- NOT LOGGING
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
SharedFlow是一股热流。也许你应该创建它
MutableSharedFlow(
replay = 0,
onBufferOverflow = BufferOverflow.DROP_OLDEST,
extraBufferCapacity = 1
)
Run Code Online (Sandbox Code Playgroud)
或者
MutableSharedFlow(
replay = 1,
onBufferOverflow = BufferOverflow.DROP_OLDEST
)
Run Code Online (Sandbox Code Playgroud)
我想您需要启动一个不同的协程来收集加载值,如下所示:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
lifecycleScope.launchWhenStarted {
viewModel.request()
}
lifecycleScope.launchWhenStarted {
viewModel.loading.collectLatest {
Log.d(this::class.simpleName, "onViewCreated: $it")
}
}
}
Run Code Online (Sandbox Code Playgroud)
viewModel.request()function 是一个suspend函数,它会挂起协程直到完成。但我猜它由于调用suspendfunction 而没有完成_loading.emit(),挂起直到它被收集。
或者我认为更好的是在ViewModel课堂上启动一个协程,如下所示:
// In MainViewModel
fun request() = viewModelScope.launch {
_loading.emit(true)
withContext(Dispatchers.IO) {
/* makes API request */
/* updates _stateFlow.value */
/* stateFlow value is successfully collected */
}
_loading.emit(false) // emitting boolean value
}
// In MyFragment
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
lifecycleScope.launchWhenStarted {
viewModel.loading.collectLatest {
Log.d(this::class.simpleName, "onViewCreated: $it")
}
}
viewModel.request()
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8545 次 |
| 最近记录: |