【问题标题】:Observing ViewModel LiveData from fragments without intermediary transformation variable从没有中间转换变量的片段中观察 ViewModel LiveData
【发布时间】: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())

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

问题 我不太明白为什么我不能用我的第二个实现来触发观察者。而且我也不确定我的初始实现是否是最佳或正确的。如果您熟悉此类设计,我将不胜感激。

【问题讨论】:

    标签: android kotlin mvvm android-livedata android-architecture-components


    【解决方案1】:

    我过去也遇到过类似的问题,而且大部分时间都与两件事有关:

    1. 插入/更新的dao 实例与观察livedata 的dao 实例不同。
    2. 我的livedata 对象被包裹在其他一些实时数据中并返回。简而言之,它与 dao 返回的 livedata 实例不同。

    您可以记录实例并检查它是否相同。它必须是单例的。如果您使用任何类型的依赖注入工具(例如 Dagger),请查看:https://stackoverflow.com/a/44958478/9715339

    我的猜测是,在你的情况下,它很可能是第二种情况。当您的livedata userProfileDao.load 被包裹在NetworkBoundResource.asLiveData() 中时,如果您查看NetworkBoundResource.result 的代码,它就是MediatorLiveData。 因此您不会主动收听userProfileDao 返回的相同实时数据。

    只是为了确认这是问题您可以尝试收听从 userProfileDao.load(username) 返回的直接 livedata 。使用 & see 在您的存储库中创建一个方法。

    您可以尝试更多地朝那个方向挖掘。

    【讨论】:

    • 我没有使用任何依赖注入工具。我确定房间数据库是单例的,但我不确定我的 DAO 是否是单例。从那以后,我将实现更改为使用 Flow 而不是 LiveData,并且我不再有观察数据的任何问题。所以我想排除 DAO 是问题所在。感谢您的回复。
    猜你喜欢
    • 2018-05-10
    • 1970-01-01
    • 2020-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    相关资源
    最近更新 更多