Reputation: 11901
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)
Upvotes: 1
Views: 1916
Reputation: 81578
Actually, with savedStateHandle
, the get/set
methods feel like a mistake to me. The only one that is truly reliable is getLiveData
, which you can combine into other LiveData using Transformations.switchMap
.
If you use getLiveData
with a type that is supported by android.os.Bundle
, then you get state persistence out of the box through it. If you don't, then you'll just get crashes. getLiveData
already returns a MutableLiveData
, which is why it is not a good idea to handle get/set
manually, you can vall .value =
on the MutableLiveData
from SavedStateHandle
if need be.
Upvotes: 1
Reputation: 26
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
Upvotes: 0