带有协程和 SavedStateHandle 的 liveData
liveData with Coroutines and SavedStateHandle
这个 answer 向我们展示了如何在存储库中使用 liveData
到 return 一个 LiveData
到 ViewModel
其中 View
会观察的。
现在,如果我们想使用 SavedStateHandle
怎么办?我们如何将以下代码转换为使用 liveData{}
from LiveData-Ktx?
视图模型:
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...*/}
})
我们会从使用 liveData{... emit()}
中受益吗?
我可以看到使用 SavedStateHandle
的 3 个优点:
1 - 恢复您的 viewModel 状态
2 - 当我们使用 stateHandle.set()
时它会为我们调用 .value()
3 - stateHandle.getLiveData
帮助我们初始化值(这对 Data Binding
也有帮助,例如)
我想你可以这样做
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)
}
}
如果对您有帮助,请告诉我。
P.S。
PageId 可以是当前页面的编号或其他任何页面标识符
实际上,对于 savedStateHandle
,get/set
方法对我来说是一个错误。唯一真正可靠的是 getLiveData
,您可以使用 Transformations.switchMap
.
将其合并到其他 LiveData 中
如果您将 getLiveData
与 android.os.Bundle
支持的类型一起使用,那么您可以通过它立即获得状态持久性。如果你不这样做,那么你只会崩溃。 getLiveData
已经 returns 一个 MutableLiveData
,这就是为什么手动处理 get/set
不是一个好主意,您可以在 [=17= 上调用 .value =
] 来自 SavedStateHandle
如果需要的话。
这个 answer 向我们展示了如何在存储库中使用 liveData
到 return 一个 LiveData
到 ViewModel
其中 View
会观察的。
现在,如果我们想使用 SavedStateHandle
怎么办?我们如何将以下代码转换为使用 liveData{}
from LiveData-Ktx?
视图模型:
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...*/}
})
我们会从使用 liveData{... emit()}
中受益吗?
我可以看到使用 SavedStateHandle
的 3 个优点:
1 - 恢复您的 viewModel 状态
2 - 当我们使用 stateHandle.set()
时它会为我们调用 .value()
3 - stateHandle.getLiveData
帮助我们初始化值(这对 Data Binding
也有帮助,例如)
我想你可以这样做
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)
}
}
如果对您有帮助,请告诉我。 P.S。 PageId 可以是当前页面的编号或其他任何页面标识符
实际上,对于 savedStateHandle
,get/set
方法对我来说是一个错误。唯一真正可靠的是 getLiveData
,您可以使用 Transformations.switchMap
.
如果您将 getLiveData
与 android.os.Bundle
支持的类型一起使用,那么您可以通过它立即获得状态持久性。如果你不这样做,那么你只会崩溃。 getLiveData
已经 returns 一个 MutableLiveData
,这就是为什么手动处理 get/set
不是一个好主意,您可以在 [=17= 上调用 .value =
] 来自 SavedStateHandle
如果需要的话。