简体   繁体   English

带有协程和 SavedStateHandle 的 liveData

[英]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.这个答案向我们展示了如何使用存储库中的liveDataLiveData返回给View将观察到的ViewModel
Now, what if we want to use SavedStateHandle ?现在,如果我们想使用SavedStateHandle怎么办? How can we transform the following code to use liveData{} from LiveData-Ktx ?我们如何转换以下代码以使用LiveData-Ktx中的liveData{}

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()} ?我们会从使用liveData{... emit()}中受益吗?

I can see 3 advantages of using SavedStateHandle :我可以看到使用SavedStateHandle的 3 个优点:
1 - Restore your viewModel state 1 - 恢复您的 viewModel state
2 - It calls .value() for us when we use stateHandle.set() 2 - 当我们使用stateHandle.set()时,它会为我们调用.value() )
3 - stateHandle.getLiveData helps us initialize the value (this is also helpful with Data Binding for example) 3 - stateHandle.getLiveData帮助我们初始化值(这对Data Binding也很有帮助)

Actually, with savedStateHandle , the get/set methods feel like a mistake to me.实际上,使用savedStateHandle时, get/set方法对我来说是个错误。 The only one that is truly reliable is getLiveData , which you can combine into other LiveData using Transformations.switchMap .唯一真正可靠的是getLiveData ,您可以使用Transformations.switchMap将其组合到其他 LiveData 中。

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.如果您将getLiveDataandroid.os.Bundle支持的类型一起使用,那么您将通过它获得开箱即用的 state 持久性。 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. getLiveData已经返回一个MutableLiveData ,这就是为什么手动处理get/set不是一个好主意的原因,如果需要,您可以在MutableLiveDataSavedStateHandle上使用.value =

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.让我知道它是否对您有帮助。 PS PageId it can be number of current page or other any page identifier PS PageId 它可以是当前页面的编号或其他任何页面标识符

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM