【问题标题】:Why does by repository Flow not update my viewModels livedata?为什么按存储库流不更新我的 viewModels 实时数据?
【发布时间】:2020-12-15 17:43:26
【问题描述】:

所以目前我有一个带有发出 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()

在我的活动中观察到了这样的情况

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

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

现在onContactsChange 看起来像

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

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

我想补充一点,我正在使用我的存储库的单个实例(单例),并且我认为我可以通过我可以看到我的数据这一事实来验证这一点,至少在第一次创建视图时是这样。

【问题讨论】:

    标签: android android-livedata


    【解决方案1】:

    想通了:

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

    【讨论】:

      【解决方案2】:

      回答您的问题有点困难,但我认为您的Flow 对象没有按照您想要的方式更新。

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

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

      并让您的虚拟机使用 collect 协程“订阅”它,然后您可以将所有这些数据转储到 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
      })
      

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

      【讨论】:

      • 我之前尝试过使用 collect,但实际上并没有用。当我有实际的实时更新部分时,我想担心使用 distinctUntilChanged 之类的东西,但谢谢!
      • 为什么不起作用?您是否尝试按照我提供的教程进行操作?
      • 是的。所以我没有收集到的一件事是它是从我们观察数据的不同上下文中插入的。我正在使用单例。存储库的对象,但这似乎很重要。当我从我的视图模型插入时,我看到更新没有问题。抱歉延迟回复。
      猜你喜欢
      • 2020-09-20
      • 2010-12-13
      • 2021-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-27
      相关资源
      最近更新 更多