android-mvvm
A Model-View-ViewModel library for Android apps
Features
This library helps reduce boilerplate code in android applications:
- a useful implementation of Model-View-ViewModel pattern by leveraging the new Android Data Binding.
- automating bind ViewModel with View.
- ViewModel is isolated from Activity/Fragment lifecycle. It's particularly good at surviving configuration changes when Android destroys your Activity and Views and replaces them with new ones.
What is MVVM?
Model-View-ViewModel is an architectural approach used to abstract the state and behavior of a view, which allows us to separate the development of the UI from the business logic. This is accomplished by the introduction of a ViewModel, whose responsibility is to expose the data objects of a model and handle any of the applications logic involved in the display of a view.
This approach (MVVM) is made up of three core components, each with its own distinct and separate role:
- Model - Data model containing business and validation logic
- View - Defines the structure, layout and appearance of a view on screen
- ViewModel - Acts a link between the View and Model, dealing with any view logic
Implementation with android-mvvm library
- Install android-mvvm library
repositories {
maven { url "https://dl.bintray.com/a-zaiats/maven" }
}
dependencies {
compile "io.github.azaiats.androidmvvm:androidmvvm-core:$androidmvvm_version"
compile "io.github.azaiats.androidmvvm:androidmvvm-navigation:$androidmvvm_version" // optional navigation feature
}
- Enable Data Binding
android {
dataBinding {
enabled = true;
}
}
- Create your ViewModel class by extending BaseViewModel. For example:
public class MyViewModel extends BaseViewModel {
....
}
- Each Activity, Fragment or DialogFragment that you would like to associate with a ViewModel will need either to extend MvvmActivity/MvvmFragment/MvvmDialogFragment or copy the implementation from these classes to your base activity/fragment/dialogFragment class (in case you can't inherit directly). Override
createViewModel()
to return the corresponding ViewModel (It can be created by directly or injected via DI). OverridegetBindingConfig()
to return the corresponding BindingConfig (will be described later). For example:
public class MyFragment extends MvvmFragment<FragmentMyBinding, MyViewModel> {
@Override
public MyViewModel createViewModel() {
return new MyViewModel();
}
@Override
public BindingConfig getBindingConfig() {
return new BindingConfig(R.layout.fragment_my, BR.viewModel);
}
}
How to use
BindingConfig
BindingConfig represents configuration for DataBinging creation. It contains 2 parameters:
- layout resource ID for this view
- Data Binding variable name for injecting the ViewModel. BindingConfig can be created without viewModelVariableName if the name of the binding is
viewModel
.
ViewModel
ViewModel has its own lifecycle:
- Method
onCreate()
will be called on ViewModel creation. This is a place to do any initialisation. - Method
onDestroy()
will be called before ViewModel destroying. This is a place to do any cleanup. - Method
onResume()
will be called when this ViewModel was binded to a view and the view is visible. - Method
onPause()
will be called when this ViewModel was unbinded from a view or view was paused. - Method
isRunning
tells if Activity/Fragment is in RUNNING state (in betweenonResume()
andonPause()
)
MvvmActivity/MvvmFragment/MvvmDialogFragment
After creation you can call getViewModel()
or getBinding()
if you want interact with your ViewModel or Binding. Also, if you want to add Observable.OnPropertyChangedCallback
to your ViewModel's observable field, you can call addOnPropertyChangedCallback(Observable.OnPropertyChangedCallback callback)
. This callback will be removed on activity/fragment destroy, so you needn't disturb about memory leaks.
Navigation
By MVVM pattern, ViewModel hasn't reference to View. So ViewModel can't interact with activity/fragment directly. But we need run navigation commands in our ViewModel (e.g. start new Activity or replace Fragment via FragmentManager). To resolve it, you can use some event bus library (e.g. Otto), RxJava, or androidmvvm-navigation extension. There are navigating versions of MvvmActivity/MvvmFragment/MvvmDialogFragment in this extension.
How to use
- Create your interface that extends Navigator. Add navigation methods to it.
- Create your ViewModel class by extending NavigatingViewModel.
- Extend your Activity/Fragment/DialogFragment from NavigatingMvvmActivity/NavigatingMvvmFragment/NavigatingMvvmDialogFragment to provide Navigator.
- Use
navigator
directly from your ViewModel to call it's methods. Note thatnavigator
can benull
if ViewModel is detached from View (e.g. when a screen was rotated). Alternate you can callexecuteNavigationCommand(NavigationCommand<T> navigationCommand)
. In this case, a command will be executed immediately if Navigator is attached. Otherwise, it will be saved and executed on Navigator attach.