Android MVVM - How to make LiveData emits the data it has (forcing to trigger the observer)

喜夏-厌秋 提交于 2019-12-10 13:33:49

问题


I have this ViewModel that gets a list from the network and I populate a RecyclerView with the data (MyAvailabilityRepository returns a MutableLiveData, that's why i'm using Transformations.switchMap):

class MyAvailabilityViewModel : ViewModel() {
    private val getListsParams = MutableLiveData<String>()
    private val getListsObservable = Transformations.switchMap(getListsParams) { 
        organizationId -> MyAvailabilityRepository.getSectionedLists(organizationId) 
    }

    fun getListsObservable() : LiveData<Resource<MutableList<SectionedAvailabilityList>>> {
        return getListsObservable
    }

    fun fetchLists(organizationId: String, forceRefresh: Boolean = false) {
        if (getListsParams.value == null || forceRefresh) {
            getListsParams.value = organizationId
        }
    }
}

Fragment's onActivityCreated:

override fun onActivityCreated(savedInstanceState: Bundle?) {
    ...
    viewModel.getListsObservable().observe(this, Observer { // populate RecyclerView })
    viewModel.fetchLists(organizationId)
}

Since getListParams.value is null the first time, it will set getListsParams.value = organizationId and trigger the switchMap and call the repository to get the list from the network.

When I want to force a refresh (by pull-to-refresh) and call the network again, I can use forceRefresh = true:

override fun onRefresh() {
    viewModel.fetchLists(organizationId, forceRefresh = true)
}

It will set the value of organizationId and trigger the Transformations that will then call network.

But, I have a scenario where I clear the data from my RecyclerView's adapter. If after that, the user click a button, I would like to trigger the observer again so that I re-populate the adapter with the data that the getListsObservable has already fetched. I don't want to call forceRefresh on this one cause i'm sure I already have the data and I would just like to trigger the observer again so that my UI is updated with the existing data. Since getListParams.value is not null at that point, then nothing happens when I call fetchLists(organizationId) later on.

Any idea of how I could achieve that with my current setup?


回答1:


Try removeObservers() and observe() again:

viewModel.getListsObservable().removeObservers(this)
viewModel.getListsObservable().observe(this, Observer { // populate RecyclerView })

because:

If LiveData already has data set, it will be delivered to the observer.

See the docs.

Or maybe you can change the getListsObservable() to return a MutableLiveData, then call setValue manually:

fun loadCurrentData() {
    getListsObservable.value = getListsObservable.value
}



回答2:


Yes, the answer given by Hong Duan is perfect. I am just going to extend that answer here,

The better of way doing is having an extension function.

My extension function looks like this,

fun <T> MutableLiveData<T>.forceRefresh() {
    this.value = this.value
}

Caller function looks like this,

mutableLiveDataObject.forceRefresh()

Happy Coding!!



来源:https://stackoverflow.com/questions/51073244/android-mvvm-how-to-make-livedata-emits-the-data-it-has-forcing-to-trigger-th

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!