Refreshing livedata with Retrofit request response

Viewed 2986

I have a simple app, which shows a list of movies. When a user clicks a button it should refresh the list, which means to go to Retrofit again and fetch the new list. The problem is, that this refresh doesn't work. It only fetches the list once, when I open the app.

public class MoviesViewModel extends AndroidViewModel {
    private MutableLiveData<Resource<List<Movie>>> mLastdMovieListObservable;
    private Repository mRepository;

    public MoviesViewModel(Application application) {
        super(application);
        mRepository = new Repository();
    }

    public LiveData<Resource<List<Movie>>> getMovieListLiveData() {
        if (mLastdMovieListObservable == null) {
            mLastdMovieListObservable = mRepository.getMovieList();
        }
        return mLastdMovieListObservable;
    }
}

and the Repository :

public MutableLiveData<Resource<List<Movie>>> getMovieList() {
    final MutableLiveData<Resource<List<Movie>>> data = new MutableLiveData<>();
    data.setValue(Resource.loading(null));

    mInterface.getMovies(.....).enqueue(new Callback<MovieListResponse>() {
        @Override
        public void onResponse(Call<MovieListResponse> call, Response<MovieListResponse> response) {
            if (response.isSuccessful()) {
                data.postValue(Resource.success(response.body().getResult()));
            } else {
                data.postValue(Resource.error(response.message(), null));
            }
        }
        @Override
        public void onFailure(Call<MovieListResponse> call, Throwable t) {
            data.postValue(Resource.error(t.getMessage(), null));
        }
    });

    return data;
}   

Then in the fragment it's just :

mMoviesViewModel.getMovieListLiveData().observe(this, moviesResource -> {
    if (moviesResource.status == Status.SUCCESS) {
       .....
       .....

then the button click part, when I need to fetch the list again, I'm not sure how to implement it. Anything I tried didn't work. the Repository returned the data as null right away.

2 Answers

You can use retry approach and I changed your code quickly for an example of retry and check this source for better code.LINK

Transformations.switchMap listens to retry and when it changed, swithMap will be call again.And in UI ViewModel should be config like below but in button you need to call just retry.

mMoviesViewModel.getMovieListLiveData().observe(this, moviesResource -> {
if (moviesResource.status == Status.SUCCESS) {
   .....
   .....

And in button:

mMoviesViewModel.retry()

Also ViewModel:

public class MoviesViewModel extends AndroidViewModel {
private MutableLiveData<Resource<List<Movie>>> mLastdMovieListObservable;
private Repository mRepository;
private Boolean mRetry = false;

public MoviesViewModel(Application application) {
    super(application);
    mRepository = new Repository();
    mLastdMovieListObservable = Transformations.switchMap(mRetry){
        mLastdMovieListObservable = mRepository.getMovieList()
    }
}

public LiveData<Resource<List<Movie>>> getMovieListLiveData() {
    return mLastdMovieListObservable;
}

public void retry(){
    mRetry.setValue(true)
}}

Changes for movie types can be like below:

public class MoviesViewModel extends AndroidViewModel {
private MutableLiveData<Resource<List<Movie>>> mLastdMovieListObservable;
private Repository mRepository;
private Int mMovieType = 0;

public MoviesViewModel(Application application) {
    super(application);
    mRepository = new Repository();
    mLastdMovieListObservable = Transformations.switchMap(mMovieType, type->
        mLastdMovieListObservable = mRepository.getMovieList(type)
    );
}

public LiveData<Resource<List<Movie>>> getMovieListLiveData() {
    return mLastdMovieListObservable;
}

public void setMovieType(Int movieType){
    mMovieType.setValue(movieType)
}

}

Related