Jetpack Compose LazyColumn切换列表后自动恢复原数据问题排查
问题定位与解决方案
核心问题
你的代码里每次SomeScreen重组时都会重新调用testViewModel.fetchCountryList(),导致过滤操作后,Composable因状态变化触发重组,原始数据又被重新加载,覆盖了过滤后的结果。
具体来说:testViewModel.fetchCountryList()直接写在SomeScreen的根作用域中,没有任何执行限制。当你点击按钮触发filterCountryList()后,ViewModel的stateMapCountryInfo更新,引发Composable重组,此时fetchCountryList()会再次执行,重新获取并设置原始数据集,所以LazyColumn先显示过滤数据,马上又被原始数据覆盖。
另外,SomeScreen里的stateCountryCodeMap是冗余的,直接使用collectAsState的结果即可,无需额外维护mutableStateOf。
修复步骤
限制
fetchCountryList()的执行时机
使用LaunchedEffect包裹fetchCountryList(),确保只在Composable首次启动时执行一次:@Composable fun SomeScreen(viewModel : TestViewModel){ // 直接collectAsState,无需额外的mutableStateOf val stateCountryCodeMap = viewModel.stateMapCountryInfo.collectAsState().value // 只在Composable首次启动时加载原始数据 LaunchedEffect(Unit) { viewModel.fetchCountryList() } // 触发加载过滤数据集的按钮 someRandomeButtom.click{ viewModel.filterCountryList() } ShowList( currentSelected = stateCountryCodeSelectedIndex.value, groupedCountryInfo = stateCountryCodeMap, testViewModel = viewModel ) }移除冗余的
stateCountryCodeMap变量
直接使用collectAsState返回的状态值,减少不必要的状态同步逻辑,避免潜在的状态不一致问题。
额外优化建议
- ViewModel中的
stateFilteredCountryInfo如果没有其他地方使用,可以考虑移除,直接在filterCountryList()中处理过滤后的数据并更新stateMapCountryInfo即可,减少不必要的Flow维护。 - 确保
fetchCountryList()中的IO操作是在协程中执行的(比如使用viewModelScope.launch(Dispatchers.IO)),避免阻塞主线程。
内容的提问来源于stack exchange,提问作者Vineet
相关产品推荐
相关产品推荐

