为什么存储库 Flow 不更新我的 viewModels 实时数据?

Why does by repository Flow not update my viewModels livedata?

所以目前我有一个带有发出 Flow<>

功能的 Dao
@Query("SELECT * FROM ${Constants.Redacted}")
    fun loadAllContacts(): Flow<List<Redacted>>

我是从这样的存储库中调用它的

val loadAllContacts: Flow<List<Redacted>> = contactDao.loadAllContacts()

我将存储库注入到 viewModel 的构造函数中,然后在我的 viewModel 的顶部有一个像这样的 val

val contacts: LiveData<List<Redacted>> = contactRepository.loadAllContacts.asLiveData()

在我的 Activity 中观察到的是这样

viewModel.contacts.observe(this) { contacts ->
            viewModel.onContactsChange(contacts)
        }

我的想法是将 Flow 转换为 LiveData,然后我可以从我的 activity 观察这个 LiveData 并启动此函数以在数据更新时实际更新 viewModel。

目前onContactsChange看起来像

fun onContactsChange(list: List<Redacted>) {
        Timber.i("VIEW UPDATE")
    }

问题是我只在打开 activity 时看到这个 Timber 日志,再也看不到了。我验证了数据正在进入我的数据库,并且我验证了在 activity & viewModel 打开时插入成功。但我再也没有看到来自 onContactsChange 的日志。当我关闭 activity,然后重新打开它时,我确实看到了我的新数据,这是我知道我的插入工作正常的另一个原因。

我想补充一点,我正在使用我的存储库的单个实例(单例),我想我可以通过我完全可以看到我的数据这一事实来验证这一点,至少在第一个视图时是这样制作。

要理解你的问题有点困难,但我认为我看到了你的 Flow 对象没有按照你想要的方式更新的总体问题。

this quick tutorial 之后,您似乎首先应该像您已经在做的那样在您的存储库中声明您的 Flow 对象

val loadAllContacts: Flow<List<Redacted>> = contactDao.loadAllContacts()

并通过使用 collect 协程将您的 VM 'subscribe' 连接到它,然后您可以将所有这些数据转储到 MutableLiveData 状态

data class YourState(..)

val state = MutableLiveData<YourState>()

init {
    contactRepository.loadAllContacts().collect {
        if (it.isNotEmpty()) {
            state.postValue(YourState(
                ...
            )
        }
    }
}

然后您的 Activity/Fragment 可以观察变化

viewModel.state.observe(.. { state ->
    // DO SOMETHING
})

P.S。本教程还提到,由于 Dao 的工作方式,即使是最微小的更改,您也可能会获得更新,但您可以使用 distinctUntilChanged() Flow 扩展功能来获得更具体的结果。

想通了:

注意:如果您的应用程序在单个进程中运行,则在实例化 AppDatabase 对象时应遵循单例设计模式。每个 RoomDatabase 实例都相当昂贵,您很少需要在单个进程中访问多个实例。 如果您的应用程序在多个进程中运行,请在您的数据库构建器调用中包含 enableMultiInstanceInvalidation()。这样,当您在每个进程中都有一个 AppDatabase 实例时,您可以使一个进程中的共享数据库文件失效,并且这种失效会自动传播到其他进程中的 AppDatabase 实例。