ViewModel preserves data beyond the lifecycle of individual Activities i.e. it is lifecycle-aware – it will hold data for the UI even if e.g. the screen is rotated, causing the Activity to be remade. It persists from onCreate() until onCleared() (after finish() is applied to the Activity), thus helping to avoid re-querying a data source repeatedly upon Activity changes. This goes beyond the savedInstanceState which is limited to small amounts of data which can be easily serialised and de-serialised.
It also helps to avoid zombie threads (memory leaks), which were begun but not terminated as the Activity which created them was destroyed before they completed. When the Activity or Fragment is finished any Observers are closed, so no orphaned processes are left running.
Works in collaboration with LiveData. For more information see here. If your ViewModel needs access to the application context then extend AndroidViewModel rather than ViewModel (as below).
Caution: A ViewModel must never reference a view, Lifecycle, or any class that may hold a reference to the activity context.
To add the dependencies for ViewModel, see here.
To implement a ViewModel, first create a ViewModel class(this example corresponds to the code in the @Entity, @DAO, Build a Database and LiveData posts):
public class MainViewModel extends AndroidViewModel {
LiveData<List<ContactEntry>> contacts;
public MainViewModel(@NonNull Application application) {
super(application);
contacts = AppDatabase.getInstance(this.getApplication()).contactDao().loadAllContacts(); // Gets the List of contact entries from the instance of the database (see @DAO post)
}
public LiveData<List<ContactEntry>> getContacts() { // Create a getter for the LivaData List above
return contacts;
}
}
In your Activity, set an Observer on the getContacts() method in the ViewModel, and tell it what to do if the data changes:
MainViewModel viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
viewModel.getContacts().observe(this, new Observer<List<ContactEntry>>() {
@Override
public void onChanged(@Nullable List<ContactEntry> contactEntries) {
mAdapter.setContacts(contactEntries); // Code to run if data changes
}
});
For applications which require variables to be passed to the ViewModel refer to the ViewModelFactory post. The Factory holds a template for creating ViewModels that you can customise to allow passing arguments into the ViewModel constructor.