[英]Observing LiveData in ViewModel best practices
我正在尋找在ViewModel
中觀察數據的最佳方式。
我正在使用 MVVM + 數據綁定。
存儲庫:
private val data = MutableLiveData<String>()
suspend fun getData(): LiveData<String> {
return withContext(IO) {
val response = apiRequest { api.getData() }
data.postValue(response)
data
}
}
它從服務器請求數據並返回實時數據。 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
的情況下從存儲庫中獲取數據:
存儲庫
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
}
如果我認為問題正確,我認為您可以在LiveData
上使用map
轉換。
也許最好更改存儲庫代碼,如下所示:
private val reload = MutableLiveData<Unit>()
val data: LiveData<String> =
reload.switchMap {
liveData(IO) {
emit(apiRequest { api.getData() })
}
}
fun reload() {
reload.postValue(Unit)
}
然后,在使用 map 轉換的ViewModel
中,您可以截取發射值:
val data: LiveData<String> =
repository.data.map {
gotData(it)
it
}
fun reload() {
repository.reload()
}
使用此結構,您將能夠在每次需要時調用 ViewModel 的reload()
,從而從 api 獲取新數據並將其發送到 ViewModel 的data
上。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.