我正在寻找最佳方法来观察 ViewModel
中的数据。
我正在使用 MVVM + DataBinding。
仓库:
private val data = MutableLiveData<String>()
suspend fun getData(): LiveData<String> {
return withContext(IO) {
val response = apiRequest { api.getData() }
data.postValue(response)
data
}
}
这段代码从服务器请求数据并返回实时数据。ViewModel 必须观察数据的变化。
ViewModel:
suspend fun getData() {
val data = repository.getData()
MediatorLiveData<String>().apply {
addSource(data) {
gotData(it)
removeSource(data)
}
observeForever { }
}
}
private fun gotData(data: String) {
//use data
}
ViewModel使用MediatorLiveData
来观察来自仓库的LiveData
的变化。我已将该数据作为源添加以观察更改,并在触发后将其删除,以防多次获取数据时多次触发事件。必须有一个虚拟观察者连接到MediatorLiveData
,以便触发MediatorLiveData
的onChange方法。
假设我只需要数据来隐藏/显示视图(甚至向我的recyclerview适配器填充数据)。那么,我只需调用下面的代码并像这样使用Observable和DataBinding:
val adapter: ObservableField<DataAdapter> = ObservableField()
val recyclerviewVisibility: ObservableField<Int> = ObservableField(View.GONE)
...
...
recyclerviewVisibility.set(View.VISIBLE)
adapter.set(DataAdapter(dataList))
所以我不需要将数据传递给Fragment或Activity来使用viewLifecycleOwner。 同时我也不能在ViewModel中使用observeForever,因为它可能会在某些情况下多次触发onChange方法。
是否有更好的方法在ViewModel中获取和观察数据?
解决方案: 我已经发现实现我的目标的最佳方法是从存储库中获取数据而不使用LiveData: Repository
suspend fun getData() : String{
return apiRequest { api.getData() }
}
视图模型
suspend fun getData(){
val data = repository.getData()
gotData(data)
}
fun gotData(data: String) {
//use data
}
现在这个变得更简单了。
额外奖励:
扩展:
fun <T : Any> ViewModel.request(request: suspend () -> (T), result: (T) -> (Unit) = {}) {
viewModelScope.launch {
result(request())
}
}
用法:
request({request.getData()}) {
//use data
}
reload.switchMap
显示了“未解决的引用”错误。因此,liveData(IO)
和emit
也显示相同的错误。 - Amirbuild.gradle
中添加implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
。 - aminographydata
上设置了观察者吗? - aminography