如何将 ViewModel 状态与(房间)数据库同步?

问题描述 投票:0回答:1

我一直在阅读大多数 Android 文档等,但我找不到有关此主题的信息。 我知道如何在 viewModel 中创建和编辑状态,如许多 Android 代码实验室中所述。但我不确定如何将 viewModel 内部的状态与数据库数据连接起来。

关于我的应用程序

  • 应用程序应在主屏幕上显示对象列表
  • 应用程序应该将此对象列表存储在我的房间数据库中
  • 用户应该能够将对象添加到此列表中

这是我的视图模型:

@HiltViewModel
class MyViewModel @Inject constructor(
    private val myRepository: MyRepository
) : ViewModel() {

    private val _list = getList().toMutableStateList()
    val List: List<MyEntity>
        get() = _list

    private fun getList(): List<MyEntity> {
        return myRepository.getList()
    }

    fun addEntity(entity: MyEntity) {
        myRepository.upsertMyEntity(entity)
    }
}

在我的可组合项中,我像这样初始化 viewModle:

myViewModel: MyViewModel = hiltViewModel<MyViewModel>()

在可组合项中,我检索列表的值,如下所示:

myViewModel.List

问题

使用给定的代码,我的 ViewModel 仅在启动时获取列表的数据库状态一次

private val _list = getList().toMutableStateList()

MutableStateList 如何知道我向数据库添加了一个对象? 反之亦然,数据库怎么知道我向列表中添加了一个对象?

可能的解决方案

我可以将 viewModel 中的“addEntity”函数编辑为以下内容:

fun addEntity(entity: MyEntity) {
    myRepository.upsertMyEntity(entity)
    _list.add(entity)
}

但这是最佳实践吗? MutableStateList 不应该以某种方式直接连接到数据库吗? 这样,感觉就像我正在手动向单一事实来源(我的数据库)添加一些内容并手动更新我的状态,这可能最终会处于与我的数据库不同的状态。例如,如果数据库抛出异常,但 ui 状态无论如何都会改变。

android android-jetpack-compose android-room android-viewmodel
1个回答
0
投票

如果您将 Dao 更改为返回

Flow<List<MyEntity>>
,Room 将创建一个流,当数据库中发生更改时,该流将自动更新其值。您的视图模型只是将其转换为
StateFlow
:

val list: StateFlow<List<MyEntity>> = myRepository.getList()
    .stateIn(
        scope = viewModelScope,
        started = SharingStarted.WhileSubscribed(5_000),
        initialValue = emptyList(),
    )

现在,您的可组合项可以简单地将流收集到 Compose

State
中,如下所示:

val list: List<MyEntity> by myViewModel.list.collectAsStateWithLifecycle()

(需要在gradle中依赖

androidx.lifecycle:lifecycle-runtime-compose

撰写中的此列表现在将始终包含数据库的当前状态:如果您添加新值,它也会自动更新。

addEntity
可以保持原样,它的唯一责任是更新数据库,而不是ui状态。

© www.soinside.com 2019 - 2024. All rights reserved.