为什么存储库 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 实例。
所以目前我有一个带有发出 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 实例。