Karol Lisiewicz
Karol Lisiewicz

Reputation: 674

Architecture Components refresh LiveData

I'm struggling with the correct way of refreshing data on the master-detail view using Architecture Components. I have a single-top master activity that displays a list of favourite movies. When I go to details view, add/remove movie from favourites and close the details view the master view's the data stays unsync. I initialize view model in the onCreate method:

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
   moviesViewModel = ViewModelProviders
                    .of(this, viewModelFactory)
                    .get(MoviesViewModel.class);
   moviesViewModel.getMovies(FAVOURITES).observe(this, this::show);
}

View Model is also quite straight forward:

@NonNull
LiveData<Resource<List<Movie>>> getMovies(Criterion criterion) {
   movieRepository.fetchBy(criterion)
                .doOnSubscribe(it -> moviesLiveData.setValue(Resource.loading()))
                .subscribe(
                        movies -> moviesLiveData.setValue(Resource.success(movies)),
                        throwable -> moviesLiveData.setValue(Resource.error(throwable))
                );

The simplest solution would be to force to refresh the view every time it becomes active:

@Override
public void onResume() {
   super.onResume();
   moviesViewModel.getMovies(FAVOURITES).observe(this, this::show);
}

But I don't really like this approach since it will result in a refresh when screen orientation changes and also when an activity comes from the background.

It's also possible to start details activity for result and refresh data only when it has changed, but I also don't think this is how it should be done this way in the reactive approach.

Moreover, I was thinking about subscribing for database changes in the cotent resolver and updating the Flowable with new content everytime data changes, but I'm convinced whether it will work since when it the change occurs the live data observer (master view) is in pause mode so it will not be notified, am I right?

Upvotes: 4

Views: 3388

Answers (2)

Carson Holzheimer
Carson Holzheimer

Reputation: 2963

There are a few ways you can manage refreshing your master view.

  1. You could use a shared ViewModel for this situation. If both the master and detail view are fragments, all you have to do is use the same viewmodel, passing in the activity or the containing fragment as the scope, eg ViewModelProviders.of(parentFragment!!, viewModelFactory). Then your moviesLiveData can be observed by both master and detail pages. **Note that the latest version of Navigation allows you more finely defined scopes by tying the ViewModel to a specific nav graph.
  2. If you are using activities for your pages, you can pass the movies results information back to the master page via startActivityForResult, setResult in the detail screen, and retrieve the information in onActivityResult
  3. You can cache the result of the network request somewhere other than the viewmodel. Typically you might have a Singleton repository that retrieves your data. You could use LiveData in the same pattern as with ViewModels.
  4. You can also observe your database as you suggest. Don't worry about it being in pause mode! That's the point of LiveData, it stores the latest update and delivers it again whenever something observes it.

Upvotes: 2

You could use livedata also for the database in order to update changes from db -> vm -> ui

Upvotes: 1

Related Questions