【问题标题】:Android MediatorLiveData source subscription does not triggerAndroid MediatorLive 数据源订阅未触发
【发布时间】:2019-06-21 17:12:15
【问题描述】:

在我的项目中,我使用了稍微修改的存储库模式:

  • 数据源(例如 API、数据库)。提供实体的 CRUD
  • 特定数据的存储库(例如 UserRepository、SettingsRepository),用于处理数据源的协调(例如,通过 API 调用更新数据库)。提供高于 CRUD 的基本功能
  • 使用存储库并从存储库调用创建流程的 ViewModel(例如,使用 UserRepository 同步用户数据,然后使用 SettingsRepository 为用户同步设置)
  • 视图是数据绑定的

在我的存储库中,我使用公开的 LiveData 字段来传达状态 - 例如说 UserRepository 将有一个公共类型 LiveData、私有 MediatorLiveData 的 currentUser 字段,并且它将链接到一个私有字段,该字段包含要检索的当前用户 ID。

但是,出于某种原因,这些订阅(使用 MediatorLiveData 的 addSource() {} 方法)不会触发。

一个几乎 1:1 的示例(由于 NDA 替换了型号名称)如下:

abstract class BaseRepository: ViewModel(), KoinComponent {

    val isLoading: LiveData<Boolean> = MutableLiveData<Boolean>().apply { postValue(false) }

}


class UserRepository: BaseRepository() {

    private val client: IClient by inject() // Koin injection of API client
    private val sharedPref: SharedPrefManager by inject() // custom wrapper around SharedPreferences

    private val currentUserId = MutableLiveData()

    val currentUser: LiveData<User> = MediatorLiveData()
    val users: LiveData<List<User>> = MutableLiveData()

    init {
        (currentUser as MediatorLiveData).addSource(currentUserId) { updateCurrentUser() }
        (currentUser as MediatorLiveData).addSource(users) { updateCurrentUser() }

        (currentUserId as MutableLiveData).postValue(sharedPref.getCurrentUserId())
        // sharedPref.getCurrentUserId() will return UUID? - null if 
    }

    fun updateCurrentUser() {
        // Here I have the logic deciding which user to push into `currentUser` based on the list of users, and if there's a `currentUserId` present.
    }
}

通过实施此示例,updateCurrentUser() 永远不会被调用,即使对其他 LiveData 字段的订阅发生并且在对 currentUser 对象进行调试时可见。

通过addSource 进行的相同订阅在其他存储库中也可以正常工作,并且它们的构建方式与上述完全相同。

这里可能出了什么问题?

【问题讨论】:

    标签: android android-livedata mutablelivedata


    【解决方案1】:

    MediatorLiveData 将不会观察源 LiveData 如果它没有订阅任何观察者。只要您订阅currentUser,就会立即调用updateCurrentUser()

    【讨论】:

    • currentUser 有订阅者 - 它被用于 UI 本身的多个数据绑定中(currentUser 通过 val currentUser: LiveData&lt;User&gt; = repo.currentUser 传递给 ViewModel),我有一些依赖的 MediatorLiveData 从中提取信息所述来源(在 VM 中公开的 User 字段是订阅 VM 的 currentUser 的 MediatorLiveData 字段,即 repo 的 currentUser)。
    • 我已经测试了您提供的代码,它可以按原样运行。尝试将日志放在不同的地方,看看哪个步骤失败了。
    • 嗯,我要试试。有什么建议可以在我希望从外部更新和订阅可空字段的存储库中使用什么来代替 MediatorLiveData?
    猜你喜欢
    • 1970-01-01
    • 2018-07-07
    • 2019-09-18
    • 2021-04-24
    • 1970-01-01
    • 2020-10-08
    • 2018-07-16
    • 2016-10-28
    • 1970-01-01
    相关资源
    最近更新 更多