如何将Proto Datastore的UserData整合到FileUiState供Composable使用?
解决方案
要将ProtoDatastore保存的UserData整合到FileUiState中,让Composable组件可以直接访问,只需按以下步骤修改代码:
1. 更新FileUiState的Loaded状态
首先修改FileViewModel中的FileUiState.Loaded类,新增userData参数来承载用户偏好数据:
sealed class FileUiState { data object Empty : FileUiState() data object Loading : FileUiState() // 新增userData参数 class Loaded(val itemState: FileItemUiState, val userData: UserData) : FileUiState() class Error(val message: String) : FileUiState() }
2. 在ViewModel中合并文件数据与用户数据流
原uiState仅依赖fileRequest流,现在需要同时监听fileRequest和userDataRepository.userData两个流,通过combine操作符合并数据,确保UI状态能同时反映文件内容和用户偏好:
val uiState: StateFlow<FileUiState> = combine( fileRequest, userDataRepository.userData ) { request, userData -> Pair(request, userData) } .flatMapLatest { (request, userData) -> request?.let { loadDataFlow(it, userData) } ?: flowOf(FileUiState.Empty) } .stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(5_000), initialValue = FileUiState.Empty, )
同时修改loadDataFlow方法,新增userData参数,在文件加载完成后将用户数据传入Loaded状态:
private fun loadDataFlow(fileRequest: FileRequestt, userData: UserData): Flow<FileUiState> = flow { emit(FileUiState.Loading) try { val result = getFileUseCase(fileRequest) emit(FileUiState.Loaded(FileItemUiState(result), userData)) } catch (error: Exception) { emit(FileUiState.Error(ExceptionParser.getMessage(error))) } }
优化方案(可选)
如果UserData更新频繁但文件数据无需重复加载,可以调整逻辑:仅在fileRequest变化时重新读取文件,userData更新时仅同步到已加载的状态中,减少不必要的文件IO:
val uiState: StateFlow<FileUiState> = fileRequest .flatMapLatest { request -> if (request == null) flowOf(FileUiState.Empty) else { loadDataFlow(request) .combine(userDataRepository.userData) { fileState, userData -> when (fileState) { is FileUiState.Loaded -> FileUiState.Loaded(fileState.itemState, userData) else -> fileState } } } } .stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(5_000), initialValue = FileUiState.Empty, ) // 对应的loadDataFlow无需再接收userData参数 private fun loadDataFlow(fileRequest: FileRequestt): Flow<FileUiState> = flow { emit(FileUiState.Loading) try { val result = getFileUseCase(fileRequest) emit(FileUiState.Loaded(FileItemUiState(result), UserData())) // 初始占位,后续会被合并的userData覆盖 } catch (error: Exception) { emit(FileUiState.Error(ExceptionParser.getMessage(error))) } }
3. 在Composable中访问UserData
现在在FileScreen的Loaded分支里,可直接从uiState中获取userData并使用:
is FileViewModel.FileUiState.Loaded -> item { // 直接访问用户偏好数据 FileToolbar(uiState = uiState, userData = uiState.userData) FileResourceCardExpanded(uiState.itemState) // 示例:根据userData调整UI,比如显示用户偏好的字体大小、主题色等 }
内容的提问来源于stack exchange,提问作者A. Cedano
相关产品推荐
相关产品推荐

