Deep dive inside of Android’s ViewModel (Architecture Components)

Google I/O 17 announced some very exciting architecture components all android developers can use. These components help tackle common problems that continue to recur during the Android development process. One common problem in particular includes how data is retained between configuration changes (Activity recreation) while achieving no memory leaks during the process. Google now has a solution for us, the ViewModel. This article dissects the source code of how the ViewModel actually addresses this problem.

What is the ViewModel?

The official documentation describes it as the following:

public abstract class ViewModel {
/**
* This method will be called when this ViewModel is no longer used and will be destroyed.
* <p>
* It is useful when ViewModel observes some data and you need to clear this subscription to
* prevent a leak of this ViewModel.
*/
@SuppressWarnings("WeakerAccess")
protected void onCleared() {
}
}

How does a ViewModel survive configuration changes?

Before digging into the source code, first we observe how a ViewModel is obtained. We take a simple LoginActivity with a LoginViewModel as an example:

LoginViewModel model = ViewModelProviders.of(this).get(LoginViewModel.class);
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity) {
initializeFactoryIfNeeded(activity.getApplication());
return new ViewModelProvider(ViewModelStores.of(activity), sDefaultFactory);
}
private final Factory mFactory;
private final ViewModelStore mViewModelStore;
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
//noinspection TryWithIdenticalCatches
try {
return modelClass.getConstructor(Application.class).newInstance(mApplication);
} catch { //RuntimeExceptions if we couldn't create }
}
return super.create(modelClass);
}

So…how does the implementation retain state?

The secret is exposed within the ViewModelStores.of(activity).

@MainThread
public static ViewModelStore of(FragmentActivity activity) {
return holderFragmentFor(activity).getViewModelStore();
}
public HolderFragment() {
setRetainInstance(true);
}

Putting it all together, here is a simple diagram expressing the relationship:

SWE at Google

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store