As usual, this year’s Google I/O saw plenty of Android-related announcements.
In this series of quick tips, we’re going to take a closer look at some of the software updates and new releases you can get your hands on today.
In this first post, we’re going to look at a collection of libraries that aims to take the pain out of lifecycle management, by giving you a way to build lifecycle-aware components that can track and react to lifecycle events automatically. I’ll also be providing a brief introduction to two other components that have been designed to use with these new lifecycle-aware components: LiveData and Room.
LifecycleOwner and LifecycleObserver
Respecting the lifecycle of your Activity
s and Fragment
s is crucial to creating a successful app. Get these fundamentals wrong, and you’re going to wind up with memory leaks that cause your app to lag, and potentially even crash.
Another recurring problem you may encounter with lifecycle management is attempting to update your app’s UI when the activity or fragment isn’t in a valid state. For example, if an Activity
receives a callback after it’s been stopped, then it’s pretty likely that your app is going to crash.
To help you avoid all the headaches that come with lifecycle management, Google has announced a new set of lifecycle-aware components that can track the lifecycle of an activity or fragment, and adjust their behaviour accordingly.
You can access these Android Architecture Components via Google’s Maven repository today. However, they are still in alpha, so you should expect some breaking changes before the 1.0 release.
In particular, the Fragment
and AppCompatActivity
classes currently cannot implement the new LifecycleOwner
interface. You'll need to use the temporary LifecycleActivity
and LifecycleFragment
classes until the Android Architecture Components reach their 1.0 release. These classes will be deprecated as soon as Android’s fragments and Activities have been updated to support the lifecycle components.
To start experimenting with these components, you’ll need to add the Google Maven repository to your project-level build.gradle file:
allprojects { repositories { jcenter() //Add the Google Maven repository// maven { url 'https://maven.google.com' } } }
Then, open your module-level build.gradle file, and add the following:
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile "android.arch.lifecycle:runtime:1.0.0-alpha1" compile "android.arch.lifecycle:extensions:1.0.0-alpha1" annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha1"
There are a few Android Architecture Components, but in this article we’re just going to focus on the following two:
LifecycleOwner
: This is something that has a lifecycle, such as anActivity
orFragment
.LifecycleObserver
: This is a class that can monitor a component's lifecycle status via annotated methods. These methods are called whenever the associated component enters the corresponding lifecycle state.
By moving the code that monitors and reacts to lifecycle events into a separate LifecycleObserver
, you can prevent your activity or fragment’s lifecycle-related methods (such as onStart
and onStop
) from ballooning out of control, making your code much more human-readable.
In the following example, we’re implementing LifecycleObserver
, and then using the @OnLifeCycleEvent
to react to various lifecycle events:
import android.arch.lifecycle.Lifecycle; import android.arch.lifecycle.LifecycleObserver; import android.arch.lifecycle.OnLifecycleEvent; public class SecondActivity implements LifecycleObserver { ... ... ... lifecycle.addObserver(this); } @OnLifecycleEvent(Lifecycle.Event.ON_START) void start() { //When the Activity enters an ON_START state, do something// } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) void stop() { //When the Activity enters an ON_STOP state, do something// } //When the Activity is destroyed, unregister the LifecycleObserver// @OnLifecycleEvent(Lifecycle.Event.ON_DESTORY) void cleanup() { lifecycle.removeObserver(this); } }
Then, in the Activity
you want to monitor, extend LifecycleActivity
to get access to the LifecycleObserver
information:
public class MainActivity extends LifecycleActivity {
Many operations can only be performed when a fragment or activity is in a specific state. You can use lifecycle.getState
to quickly and easily check the component’s current state, and then only perform the action if the component is in the correct state:
if (lifecycle.getState().isAtLeast(STARTED)) {
LiveData
LiveData
is an observable data holder that exposes a stream of events that you can observe.
The key difference between LiveData
and other observables, such as RxJava, is that LiveData
is aware of the Android lifecycle. LiveData
respects the lifecycle state of your Activities, fragments, and services, and will manage subscriptions for you.
Crucially, if an observer’s lifecycle is inactive, then the observer won’t be notified about changes to the LiveData
, preventing application crashes that can occur when you try to push updates to stopped components.
To use LiveData
, you just need to tell your Activity
that you want to observe some data within the lifecycle:
public class MyActivity extends LifecycleActivity { public void onCreate(Bundle savedState) { LiveData<User> userData; //Get user data from somewhere// userData.observe(this, user -> { }); } }
As soon as the activity starts, it’ll begin observing the LiveData
, and your observer will receive an update whenever the value of that LiveData
changes. If the Activity
is destroyed, then the subscription will be removed automatically.
If an Activity
is stopped due to a configuration change, then the new instance of that Activity
will receive the last available value from the LiveData
.
LiveData
does share some similarities with RxJava, but the official word from Google I/O is that if you’re familiar with RxJava, then you should start your Android projects with LiveData
, as it’s designed to be simple, fast and lightweight, and integrates well with the Android framework. You can then add RxJava features if you need additional reactive programming functionality.
If you do want to use LiveData
with the RxJava 2 library, then open your module-level build.gradle file and add the following:
compile "android.arch.lifecycle:reactivestreams:1.0.0-alpha1"
You’ll then be able to use the following methods:
toPublisher
: Adapts theLiveData
stream to a ReactiveStreamsPublisher
.
public static <T> Publisher<T> toPublisher( final LifecycleOwner lifecycle, final LiveData<T> liveData) {
fromPublisher
: Creates an observableLiveData
stream from a ReactiveStreams publisher.
public static <T> LiveData<T> fromPublisher(final Publisher<T> publisher)
The Room Library
Although the Android framework has built-in support for working with raw SQL content, these APIs are fairly low-level and time-consuming to implement.
Google’s new Room library promises to abstract away some of the underlying implementation details of working with raw SQL tables and queries. It should also help reduce the amount of boilerplate code you need to write in order to convert SQL queries into Java data objects, and it features a Migration
class that you can use to update your app without losing the user’s data.
To use Room, open your module-level build.gradle file and add the following to the dependencies
section:
compile "android.arch.persistence.room:runtime:1.0.0-alpha1" annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
When performing queries, you'll typically want your UI to update automatically whenever the data changes; with Room, you can achieve this by using a return value type of LiveData
.
Finally, if you’re using RxJava, then your Room queries can also return RxJava 2’s Publisher
and Flowable
objects. To use RxJava with Room, you’ll need to open your module-level build.gradle file and add the following to the dependencies
section:
compile 'android.arch.persistence.room:rxjava2:1.0.0-alpha1'
Conclusion
In this quick tip, I showed you how to manage the Android lifecycle, using LifecycleOwner and LifecycleObserver, and introduced you to two additional components you may want to use alongside the Lifecycle project.
In the next tip, we’re going to look at Google’s plans to merge Android Wear UI components with the Android Support Library, as well as some additions to Android Wear complications.
In the meantime, check out some of our other tutorials and our video courses on Android app development!
- AndroidCreate a Voice-Controlled Android App
- Android SDKServerless Apps With Firebase Cloud Functions
- Android SDKReactive Programming Operators in RxJava 2