从没有中间转换变量的片段中观察ViewModel LiveData



我在android应用程序中遵循MVVM架构。(https://developer.android.com/jetpack/guide)。我的所有存储库函数都返回一个NetworkBoundResource对象。你可以从jetpack指南链接中阅读更多关于这个设计实现的信息,或者在这里查看谷歌的示例项目

在这个特殊的问题中,当我按下屏幕时,我试图通过网络重新获取信息。

当前工作实施

片段侦听器(屏幕下拉时触发(

binding.refresh.setOnRefreshListener {
profileViewModel.refreshUserProfile()
}

然后在我的ViewModel中,我有一个MutableLiveData,它更新了这个调用的函数的值

private val _refresh = MutableLiveData<Boolean>()
fun refreshUserProfile() {
_refresh.value = true
}

_refresh.value发生变化时,会触发switchMap

val currentUserProfile: LiveData<Resource<UserProfile>> = _refresh.switchMap {
if (it) {
repository.getCurrentUserProfile(_username.value.toString())
} else {
AbsentLiveData.create()
}
}

存储库功能


fun getCurrentUserProfile(username: String): LiveData<Resource<UserProfile>> {
return object : NetworkBoundResource<UserProfile, UserProfile>(AppExecutors.getInstance()) {
override fun saveCallResult(item: UserProfile) {
userProfileDao.update(item)
}
override fun shouldFetch(data: UserProfile?): Boolean {
return true
}
override fun loadFromDb(): LiveData<UserProfile> {
return userProfileDao.load(username)
}
override fun createCall(): LiveData<ApiResponse<UserProfile>> {
return networkService.userProfileService.getUserProfileAsync(
token,
username
)
}
}.asLiveData()
}

然后回到我的片段,我有一个关于这个currentUserProfileViewModel变量的观测者

profileViewModel.currentUserProfile.observe(viewLifecycleOwner, { userProfileResult ->
when (userProfileResult.status) {...}
})

我想做什么

我想跳过设置_refresh.value = true的步骤。相反,直接观察存储库的功能如下:

val currentUserProfile: LiveData<Resource<UserProfile>> = 
repository.getCurrentUserProfile(_username.value.toString())

但是这个实现不会触发片段中的观察者。

问题我不太明白为什么我的第二个实现不能触发observer。我也不确定我最初的实现是否是最佳的或正确的。我将感谢任何形式的反馈,特别是如果你熟悉这种类型的设计。

我过去也遇到过类似的问题&大多数时候,它与两件事有关:

  1. 插入/更新的dao实例与观察livedata的dao实例不同
  2. 我的CCD_ 7对象被其他一些livedata&返回。简而言之,它与dao返回的livedata实例不同

您可以记录实例&检查是否相同。它需要是singleton。如果您正在使用任何类型的依赖注入工具(例如Dagger(,请检查以下内容:https://stackoverflow.com/a/44958478/9715339

我的猜测是,在你的情况下,这很可能是第二种情况。当你的livedatauserProfileDao.load被包裹在NetworkBoundResource.asLiveData()&如果你看一下NetworkBoundResource.result的代码,它是一个MediatorLiveData。所以您没有在积极地监听userProfileDao返回的相同实时数据。

为了确认这就是问题所在,您可以尝试收听从userProfileDao.load(username)返回的直接livedata。使用&看见

你可以试着朝那个方向挖更多。

最新更新