Android Architecture Components by Example

At Google I/O 2017, the Android Framework team announced the new Android Architecture Components. Namely ViewModel, LiveData and other lifecycle-aware components. In this post we will explore their value. The source code for all examples used is linked at the bottom of the post.
Say we have a simple app with a Button
and a TextView
displaying the number of times the button was clicked.

Here is the Activity implementation:
And here is the layout:
Problem
After clicking the button a few times and then rotating the screen, the click count gets reset since the Activity gets destroyed and recreated after the screen rotation and we have not implemented any logic to preserve this data during the Activity lifecycle.
Traditionally, some of the common ways to avoid losing data during configuration changes, such as screen rotation, include saving and restoring state manually via onSaveInstanceState(Bundle outState)
and onRestoreInstanceState(Bundle savedInstanceState)
, using Activity#onRetainNonConfigurationInstance()
or bypassing the whole destroy-and-recreate cycle via Fragment#setRetainInstance(true)
.
ViewModel solution
The new ViewModel
API from Google is perfectly suited to address this issue. It provides a way to create and retrieve data objects that are bound to a specific lifecycle owner such as Activity or Fragment (commonly referred to as UI controllers).
Instances of the
ViewModel
survive configuration changes. Therefore, rotating the screen does not affectViewModel
data.
Let’s implement ViewModel
that holds the click count.
And here is the Activity using theClickCounterViewModel
:
And finally the xml layout file:
Now, click counts survive rotations. How is it accomplished? Take a look at this line in the ViewModelDemoActivity
:
viewModel = ViewModelProviders.of(this).get(ClickCounterViewModel.class);
ViewModelProviders
requests ViewModel
of type ClickCounterViewModel
for this Activity. On the initial load, since the ViewModel
does not exist yet, one will be created and returned. On subsequent calls, the same instance of ViewModel
will be returned.
ViewModel with non-default constructor
What if your ViewModel
is more complicated and needs to inject dependencies via constructor? For instance, let’s instantiate our ViewModel
by passing a basic logging interceptor for logging clicks.
ViewModel
requiring constructor parameters is instantiated via a custom factory class that implementsViewModelProvider.Factory
interface.
Here is a sample ViewModel
with a non-default constructor:
Where the interceptor is:
And the Activity is:
Where the factory used to generate instances of the LoggingClickCounterViewModel
is:
These lines from the Activity are the most interesting:
ViewModelProviders
requests ViewModel
of type LoggingClickCounterViewModel
for this Activity but this time, in addition to passing the Activity instance via this
keyword, we also pass a custom factory that knows how to instantiate the LoggingClickCounterViewModel
via non-default constructor: LoggingClickCounterViewModel(ClickLoggingInterceptor loggingInterceptor)
LiveData
LiveData
allows your LifecycleOwner
to receive updates from your ViewModel
by observing the changes while the Activity is Started or Resumed. LiveData
manages observer subscriptions by pausing subscriptions to stopped LifecycleOwner
objects, and cancelling subscriptions to LifecycleOwner
objects in onDestroy()
.
Here is the ViewModel
that supports LiveData
:
And here is the Activity that uses it:
And the layout:

When you launch this activity, while it’s visible, you will observe the following in the log file printed every second:
Updating timer
Updating timer
...
But as soon as your activity gets backgrounded (for example, by opening another app), the log statements stop appearing since the activity stops observing the LiveData
. Once the activity is visible again, the timer starts updating the view again and the logs appear again.
LifecycleObserver
An activity that extends AppCompatActivity
is automatically a LifecycleOwner
. Multiple LifecycleObserver
s can observe lifecycle changes in your activity.
It’s also possible for non-activity and non-fragments to observe lifecycle changes. Let’s implement a LifecycleObserver
reacting to your activity’s onResume()
and onPause()
callbacks:
And to associate the LifecycleOwner
with the LifecycleObserver
, you’d use the following statement (usually in your Activity’s onCreate()
): getLifecycle().addObserver(new MyObserver())
.
Once that’s done, we will get log statements “resumed observing lifecycle” and “paused observing lifecycle” whenever the activity is in resumed or paused state respectively.
You can query the current lifecycle state inside your LifecycleOwner
such as activity using getLifecycle().getCurrentState()
Things to Remember
- Never store references to Context or View in your
ViewModel
orLiveData
. This will result in memory leaks asViewModel
andLiveData
will outlive their lifecycle owner activity or fragment. - If you need an application context in your
ViewModel
orLiveData
(for accessing system services, etc.), instead of extendingViewModel
, extendAndroidViewModel
and callgetApplication()
to retrieve the application. - The
onCleared()
method ofViewModel
can be used to unsubscribe or clear references to objects with a longer lifecycle, but not for clearing references toContext
orView
objects. - Multiple fragments can observe the same
ViewModel
when their host activity is theLifecycleOwner
simply by calling:ViewModelProviders.of(getActivity()).get(MyViewModel.class)
. Alternatively, when fragments areLifecycleOwner
s themselves, theirViewModel
instances are independent of each other. - In MVP and MVVM Android architecture, which I recommend you use in your apps, using
ViewModel
makes the View component leaner and the rest of the app more testable. The View component is usually implemented as Activity, Fragment or a custom view or their combination. - Remember, it is not
ViewModel
’s responsibility to fetch its own data (for example, from a network). Instead,ViewModel
should delegate the work to an appropriate component (such as Use Case of Interactor). Consider injecting these components intoViewModel
via constructor (see an example above).
Recommended Reading
- Source code for this article: https://github.com/jshvarts/SimpleViewModel
- Great overview of the new Architecture components, ViewModels, A Simple Example by Lyla Fujiwara
- Android Architecture Components official docs from Google
- Android lifecycle-aware components codelab from Google
- Using ViewModel and LiveData in MVVM architecture, part 1 by Hazem Saleh
- Android ViewModels means Composition by Alex Hart
If you found this article helpful, please 👏 to recommend it to others.
Visit my Android blog to read about Jetpack Compose and other Android topics