You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 14:29:57