Search code examples
androidandroid-architecture-componentsandroid-livedatakotlin-coroutines

liveData with Coroutines and SavedStateHandle


This answer show us how can we use liveData in the repository to return a LiveData to ViewModel which the View will observe.
Now, what if we want to use SavedStateHandle? How can we transform the following code to use liveData{} from LiveData-Ktx?

ViewModel:

private val _itemLiveData = stateHandle.getLiveData<MyItem>(KEY, MyItem())
val itemLiveData: LiveData<MyItem> = _itemLiveData

suspend fun nextPage() {
    viewModelScope.launch {
        val item = repoCall...
        stateHandle.set(KEY, item)
    }
}

Activity:

viewModel.itemLiveData.observe(this, Observer {
    lifecycleScope.launch {/*...update ui...*/}
})

Will we benefit from using liveData{... emit()}?

I can see 3 advantages of using SavedStateHandle:
1 - Restore your viewModel state
2 - It calls .value() for us when we use stateHandle.set()
3 - stateHandle.getLiveData helps us initialize the value (this is also helpful with Data Binding for example)


Solution

  • I think you can do something like this

    class SomeViewModel(
        private val savedStateHandle: SavedStateHandle
        repository:ItemsRepository) : ViewModel() {
    
        companion object {
            private const val PAGE_KEY = "page_key"
        }
    
        private val _page = MutableLiveData<PageId>(savedStateHandle.get(PAGE_KEY))
    
        private val _itemLiveData = Transformations.switchMap(_page) { pageId -> repository.getNextPage(pageId) }
        val itemLiveData: LiveData<MyItem> = _itemLiveData
    
        suspend fun nextPage(pageId: PageId) {
            _page.postValue(pageId)
        }
    
        override fun onCleared() {
            super.onCleared()
            savedStateHandle.set(PAGE_KEY, _page.value)
        }
    }
    
    
    class ItemsRespository {
    
        fun getNextPage(pageId:PageId) = liveData() {
            ....
            emit(someData)
        }
    }
    

    Let me know if it helped you. P.S. PageId it can be number of current page or other any page identifier