从没有中间转换变量的片段中观察 ViewModel LiveData
Posted
技术标签:
【中文标题】从没有中间转换变量的片段中观察 ViewModel LiveData【英文标题】:Observing ViewModel LiveData from fragments without intermediary transformation variable 【发布时间】:2021-08-23 12:41:25 【问题描述】:我在我的 android 应用程序中遵循 MVVM 架构。 (https://developer.android.com/jetpack/guide)。我所有的存储库函数都返回一个 NetworkBoundResource 对象。您可以从 jetpack 指南链接阅读更多关于此设计实现的信息,或从 google here查看示例项目
在这个特定的问题中,当我在屏幕上下拉时,我试图通过网络重新获取信息。
当前的工作实施
片段监听器(屏幕下拉时触发)
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()
然后回到我的片段,我在这个 currentUserProfile
ViewModel 变量上有一个观察者
profileViewModel.currentUserProfile.observe(viewLifecycleOwner, userProfileResult ->
when (userProfileResult.status) ...
)
我要做什么
我想跳过设置_refresh.value = true
的步骤。而是像这样直接观察存储库功能:
val currentUserProfile: LiveData<Resource<UserProfile>> =
repository.getCurrentUserProfile(_username.value.toString())
但是这个实现不会触发片段中的观察者。
问题 我不太明白为什么我不能用我的第二个实现来触发观察者。而且我也不确定我的初始实现是否是最佳或正确的。如果您熟悉此类设计,我将不胜感激。
【问题讨论】:
【参考方案1】:我过去也遇到过类似的问题,而且大部分时间都与两件事有关:
-
插入/更新的
dao
实例与观察livedata 的dao
实例不同。
我的livedata
对象被包裹在其他一些实时数据中并返回。简而言之,它与 dao
返回的 livedata
实例不同。
您可以记录实例并检查它是否相同。它必须是单例的。如果您使用任何类型的依赖注入工具(例如 Dagger),请查看:https://***.com/a/44958478/9715339
我的猜测是,在你的情况下,它很可能是第二种情况。当您的livedata
userProfileDao.load
被包裹在NetworkBoundResource.asLiveData()
中时,如果您查看NetworkBoundResource.result
的代码,它就是MediatorLiveData
。
因此您不会主动收听userProfileDao
返回的相同实时数据。
只是为了确认这是问题您可以尝试收听从 userProfileDao.load(username)
返回的直接 livedata
。使用 & see 在您的存储库中创建一个方法。
您可以尝试更多地朝那个方向挖掘。
【讨论】:
我没有使用任何依赖注入工具。我确定房间数据库是单例的,但我不确定我的 DAO 是否是单例。从那以后,我将实现更改为使用 Flow 而不是 LiveData,并且我不再有观察数据的任何问题。所以我想排除 DAO 是问题所在。感谢您的回复。以上是关于从没有中间转换变量的片段中观察 ViewModel LiveData的主要内容,如果未能解决你的问题,请参考以下文章
使用 LiveData 和 ViewModel 删除项目会导致重新发射