我一直在阅读大多数 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 状态无论如何都会改变。
如果您将 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状态。