Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
181 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 Answer

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...