https://github.com/googlesamples/android-architecture
todo-mvvm-databinding
The ViewModel in the MVVM architecture plays a similar role to the Presenter in the MVP architecture. The two architectures differ in the way that the View communicates with the ViewModel or Presenter respectively:
When the app modifies the ViewModel in the MVVM architecture, the View is automatically updated by a library or framework. You can’t update the View directly from the ViewModel, as the ViewModel doesn’t have access to the necessary reference.
You can however update the View from the Presenter in an MVP architecture as it has the necessary reference to the View. When a change is necessary, you can explicitly call the View from the Presenter to update it. In this project, you use layout files to bind observable fields in the ViewModel to specific UI elements such as a TextView, or ImageView. The Data Binding Library ensures that the View and ViewModel remain in sync bi-directionally as illustrated by the following diagram.
todo-mvvm-live
Live events
A new SingleLiveEvent class is created, which extends MutableLiveData so it’s lifecycle-aware. It’s used for communication between ViewModels and UI views (activities and fragments).
Instead of holding data, it dispatches data once. This is important to prevent events being fired after a rotation, for example.
A convenient use for this is navigation. There is no reference to the View from a ViewModel so the communication between them must happen via a subscription. ViewModels expose events like openTaskEvent and views subscribe to them. For example:
private void subscribeToNavigationChanges(TaskDetailViewModel viewModel) {
// The activity observes the navigation commands in the ViewModel
viewModel.getEditTaskCommand().observe(this, new Observer<Void>() {
@Override
public void onChanged(@Nullable Void _) {
TaskDetailActivity.this.onStartEditTask();
}
});
viewModel.getDeleteTaskCommand().observe(this, new Observer<Void>() {
@Override
public void onChanged(@Nullable Void _) {
TaskDetailActivity.this.onTaskDeleted();
}
});
}
Snackbar
To show a Snackbar, you must use a static call to pass a view object:
Snackbar.make(View coordinatorLayout, String text, int length).show();
A ViewModel, however, doesn’t have the necessary reference to the view hierarchy. Instead, you can manually subscribe the snackbar to a Snackbar event. In this case the subscription is made to a SnackbarMessage which extends a SingleLiveEvent and takes a string resource ID (an integer). There’s only one snackbar and there should only be one active observer at a time. Messages are only shown once.