Jetpack Compose如何正确展示Protobuf DataStore数据并支持实时更新
问题根因
你的代码问题出在Composable层的状态声明逻辑:val address by remember { mutableStateOf(networkSettings.address) } 中,remember 包裹的逻辑仅会在首次组合时执行一次,后续 networkSettings 随DataStore更新时,address 不会同步读取新值,因此视图永远展示首次的默认值,不会触发刷新。
修复方案
方案1:最小改动适配现有代码
直接删除多余的address状态声明,直接读取监听后的值即可,修改后的Composable代码如下:
@Composable fun MyComposable(viewModel: MyViewModel) { val networkSettings by viewModel.networkSettingsLive.observeAsState(initial = NetworkSettings.getDefaultInstance()) // 无需额外套一层remember状态,直接使用实时更新的networkSettings即可 Text(text = networkSettings.address) }
如果确实需要单独提取address变量,给remember添加依赖key即可实现数据变化时自动更新:
val address by remember(networkSettings) { mutableStateOf(networkSettings.address) }
方案2:更推荐的原生Compose适配方案
无需将Flow转成LiveData再绕一层转换,直接在Compose中收集Flow作为状态,性能更高逻辑更简洁:
- ViewModel层直接暴露Flow即可:
val networkSettingsFlow = dataStore.data.catch { e -> if (e is IOException) { emit(NetworkSettings.getDefaultInstance()) } else { throw e } }
- Composable层使用
collectAsStateWithLifecycle收集状态,可自动遵循页面生命周期暂停/恢复收集,避免后台资源浪费:
@Composable fun MyComposable(viewModel: MyViewModel) { val networkSettings by viewModel.networkSettingsFlow.collectAsStateWithLifecycle( initialValue = NetworkSettings.getDefaultInstance() ) Text(text = networkSettings.address) }
注:
collectAsStateWithLifecycle需引入androidx.lifecycle:lifecycle-runtime-compose依赖,是官方推荐的页面场景Flow收集方案。
两种方案都可以满足启动加载默认值、后续数据变更实时刷新的需求。
内容的提问来源于stack exchange,提问作者CovaDax
相关产品推荐
相关产品推荐

