StateFlow在launch中正常运行,移入repeatOnLifecycle后失效
问题原因
你重构后的代码里,collect是挂起函数,会一直阻塞当前协程直到Flow结束。第一个viewModel.uiState.flowWithLifecycle(...).collect会持续占用当前协程,导致后面的scanner.barcode.collect永远无法执行,这就是功能失效的核心原因。
原来的可行代码中,你用额外的launch给第一个Flow的收集单独开了协程,两个收集任务并行执行,所以能正常工作。
修复方案
在repeatOnLifecycle的代码块内,用launch分别启动两个Flow的收集,让它们并行运行:
private fun observeUI() { viewLifecycleOwner.lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { // 给第一个Flow的收集单独开协程 launch { viewModel.uiState.flowWithLifecycle(viewLifecycleOwner.lifecycle) .collect { uiState -> uiState.error?.let { showErrorAlert(it) } uiState.success?.let { handleSuccessState(it) } handleLoadingState(uiState.isLoading) } } // 第二个Flow的收集直接在当前协程执行 scanner.barcode.collect { handleScannedBarcode(it) } } } }
也可以用coroutineScope包裹两个launch,明确保证两个收集任务在repeatOnLifecycle的生命周期范围内并行执行:
private fun observeUI() { viewLifecycleOwner.lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { coroutineScope { launch { viewModel.uiState.flowWithLifecycle(viewLifecycleOwner.lifecycle) .collect { uiState -> uiState.error?.let { showErrorAlert(it) } uiState.success?.let { handleSuccessState(it) } handleLoadingState(uiState.isLoading) } } launch { scanner.barcode.collect { handleScannedBarcode(it) } } } } } }
额外优化:当使用repeatOnLifecycle时,内部的Flow无需再调用flowWithLifecycle,因为repeatOnLifecycle已经会根据生命周期自动启停收集,简化后的代码如下:
private fun observeUI() { viewLifecycleOwner.lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { coroutineScope { launch { viewModel.uiState.collect { uiState -> uiState.error?.let { showErrorAlert(it) } uiState.success?.let { handleSuccessState(it) } handleLoadingState(uiState.isLoading) } } launch { scanner.barcode.collect { handleScannedBarcode(it) } } } } } }
内容的提问来源于stack exchange,提问作者NiceToMytyuk
相关产品推荐
相关产品推荐

