Android MediatorLiveData 源订阅未触发
Android MediatorLiveData source subscription does not trigger
在我的项目中,我使用了稍微修改过的存储库模式:
- DataSource(例如 API,数据库)。提供实体的 CRUD
- 处理数据源协调的特定数据(例如 UserRepository、SettingsRepository)的存储库(例如,从 API 调用更新数据库)。提供高于 CRUD
的基本功能
- ViewModel 使用存储库并从存储库调用中创建流(例如,使用 UserRepository 同步用户数据,然后使用 SettingsRepository 同步用户设置)
- 视图是数据绑定的
在我的存储库中,我使用公开的 LiveData<*> 字段来传达状态 - 例如表示 UserRepository 将有一个 public 类型 LiveData 的 currentUser
字段,私下为 MediatorLiveData,并且它将链接到一个包含要检索的当前用户 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
进行的相同订阅在其他存储库中工作得很好,它们的构建方式与上述完全相同。
这里可能出了什么问题?
MediatorLiveData
将不会观察源 LiveData
如果它没有任何观察者订阅它自己。 updateCurrentUser()
将在您订阅 currentUser
后立即调用。
在我的项目中,我使用了稍微修改过的存储库模式:
- DataSource(例如 API,数据库)。提供实体的 CRUD
- 处理数据源协调的特定数据(例如 UserRepository、SettingsRepository)的存储库(例如,从 API 调用更新数据库)。提供高于 CRUD 的基本功能
- ViewModel 使用存储库并从存储库调用中创建流(例如,使用 UserRepository 同步用户数据,然后使用 SettingsRepository 同步用户设置)
- 视图是数据绑定的
在我的存储库中,我使用公开的 LiveData<*> 字段来传达状态 - 例如表示 UserRepository 将有一个 public 类型 LiveData 的 currentUser
字段,私下为 MediatorLiveData,并且它将链接到一个包含要检索的当前用户 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
进行的相同订阅在其他存储库中工作得很好,它们的构建方式与上述完全相同。
这里可能出了什么问题?
MediatorLiveData
将不会观察源 LiveData
如果它没有任何观察者订阅它自己。 updateCurrentUser()
将在您订阅 currentUser
后立即调用。