Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
179 views
in Technique[技术] by (71.8m points)

android - ViewModel with Asynchronous Data Load and SavedStateHandle

I'm new to ViewModel and am trying to figure out what the best practices are for using SavedStateHandle in tandem with asynchronously loading data from an API.

My use case is that my ViewModel data should be loaded in once from the API, and after that I want the SavedStateHandle to save that data so if I come back to the fragment it doesn't perform that API call again. I only want that data refreshed from the API on a pull down to refresh mechanism in the UI, otherwise it should use the SavedStateHandle data.

I've found plenty of examples using one or the other (asynchronous data load or SavedStateHandle but not both.

Here is my initial code that does not use SavedStateHandle

class FilmsViewModel(private val savedStateHandle: SavedStateHandle): ViewModel() {
    private val filmsLiveData : MutableLiveData<List<Film>?> by lazy {
        MutableLiveData<List<Film>?>().also {
            loadFilms()
        }
    }

    fun getFilms(): LiveData<List<Film>?> {
        return filmsLiveData
    }

    fun loadFilms() {
        Log.d("FilmsViewModel", "loadFilms")
        StarWarsApiService.getFilms(object: FilmsCallback {
            override fun success(films: List<Film>?) {
                filmsLiveData.value = films
            }
        }, object: ErrorCallback {
            override fun error(error: ApiError) {
                // TODO
            }
        })
    }
}

Any ideas?

question from:https://stackoverflow.com/questions/65893412/viewmodel-with-asynchronous-data-load-and-savedstatehandle

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

By default, the way Google intended (and which DOES try to re-fetch in onStart) you would make StarWarsApiService.getFilms be suspend fun instead of callback-based, then you can do

class FilmsViewModel(private val savedStateHandle: SavedStateHandle): ViewModel() {
    val filmsLiveData = liveData {
        emit(loadFilms())
    }
}

But what you're looking for is a regular viewModelScope.launch { that saves the retrieved data in a MutableLiveData, OR into local storage (Room) that would expose a LiveData<List<T>> which would be observed by the Fragment.

SavedStateHandle isn't for data, it is for state.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...