UI 上未观察到(可变)LiveData

(Mutable)LiveData is not getting observed on UI

我在 SO 上发布了很多类似的帖子,但我仍然找不到我无法在 UI 上观察到 LiveData 的原因。

我正在从事一个以学习为目的的项目。我想要做的是从我的 Room 数据库中获取一个值并将其显示在 UI 上。为了清楚起见,我只展示了相关的代码片段。

Dao.kt

@Query("SELECT maxValue FROM DoItAgainEntity WHERE id = :id")
    fun getMaxValue(id: Int): LiveData<Int>

Repository.kt

override fun getMaxValue(activityId: Int) = doItAgainDao.getMaxValue(activityId)

ViewModel.kt

private val mMaxValue = MutableLiveData<Int>()

override fun getMaxValue(id: Int): LiveData<Int> =
   Transformations.switchMap(mMaxValue) {
            repository.getMaxValue(id)
   }

Fragment.kt

viewModel.getMaxValue(activitiesAdapter.activities[position].id)

viewModel.getMaxValue(activitiesAdapter.activities[position].id).observe(viewLifecycleOwner, Observer {
     // THIS CODE IS NEVER CALLED
     Log.d("getMaxValueObserver",it.toString())
}

如何获得 LiveData 对象中提供的 Int 值?我知道,这几乎是一个新手问题,但你能解释一下我误解了什么吗?

非常感谢。

您没有更新 LiveData,因为您在 mMaxValue 上更新了 switchMap。但是 LiveData 永远不会改变(正如我从您的示例中看到的那样)。

你其实不需要 属性 private val mMaxValue = MutableLiveData<Int>().

您可以将函数简化为:

fun getMaxValue(id: Int): LiveData<Int> = repository.getMaxValue(id)

开关地图

Returns a LiveData mapped from the input source LiveData by applying switchMapFunction to each value set on source.

在视图模型中

val mMaxValue = MutableLiveData<Int>()
override fun getMaxValue(id: Int){
    repository.getMaxValue(id).observeForEver{it ->
       mMaxValue.value = it
    }
}

并且在 Activity 或片段中:

viewModel.getMaxValue(activitiesAdapter.activities[position].id)

viewModel.mMaxValue.observe(viewLifecycleOwner, Observer {
    // THIS CODE IS NEVER CALLED
    Log.d("getMaxValueObserver",it.toString())
}

要使此代码正常工作,需要执行几个步骤。非常感谢@ChristianB 解决了这个问题。这些是他的建议:

  1. 如果Entity有多个column/field,Room返回LiveData<Int>时如何知道你想要哪个值?因此,必须返回整行(定义为 Entity 对象),这将是 ID 与参数 :id.
  2. 匹配的实体

Dao.kt

@Query("SELECT * FROM DoItAgainEntity WHERE id = :id")
 fun getMaxValue(id: Int): LiveData<DoItAgainEntity>

  1. Repository 中,您可以 filter/map 为您实际需要的任何字段。或者甚至将它映射到一个完全不同的(域)对象。

Repository.kt

override fun getMaxValue(activityId: Int): LiveData<Int> = doItAgainDao.getMaxValue(activityId).map { entity -> entity.maxValue }
  1. switchMap(someLiveData) 仅在 someLiveData 的值更改时调用,然后可以从中返回另一个 liveData。但这不是我的情况。我只是想从 LiveData 中获取一个值,该值归结为我的 DAO。所以这里不需要switchMap

ViewModel.kt

 override fun getMaxValue(id: Int) = repository.getMaxValue(id)
  1. 最后,观察LiveData对UI的作品。还应删除原始问题中对 viewModel.getMaxValue(activitiesAdapter.activities[position].id) 的重复调用。

Fragment.kt

viewModel.getMaxValue.observe(viewLifecycleOwner, Observer {
    // THIS CODE HAS NOW BEEN CALLED :)
    Log.d("getMaxValueObserver",it.toString())
    return@Observer
})
  1. 最后但同样重要的是,如果 Entity 像我的情况一样更新,首先创建数据库后,完全卸载应用程序,适当增加数据库版本,所以Room 可以运行 对数据库进行迁移!清理并重建项目,使缓存无效/重新启动。