What is Lifecycle and why should I care?

Lifecycle is a part of many Architecture Components released by Google to make the life of Android devs a whole lot easier. Lifecycle provides a set of classes and interfaces that let you better mange your application components according to your activity/fragment lifecycle. Also you need to understand how Lifecycle works before learning a very handy architecture component, LiveData.

There are a couple of good different examples provided in the official docs on Lifecycle that you should read after going through this article. This article aims to give you a simple understanding of how this component works.

Undestanding the Lifecycle Components

The basic idea here is that there is a class named LifecycleOwner which emits various lifecycle events (such as ON_CREATE, ON_PAUSE, etc) which you as an Android Developer are already familiar with. Now you can implement an interface name LifecycleObserver which listens to these events and respond accordingly.

Right now you don’t need to worry about how to create a LifecycleOwner. Your activity and fragment already implement this interface.

There are two different enums to track the lifecycle of a component, Event and State.

Event

Event is the current lifecycle that ‘happened’. So suppose your activity goes into onPause, so an event named ON_PAUSE will be fired, when it goes into onStop an event named ON_STOP will be fired. You can register to listen to these events and take some action (we will shortly see an example which will makes things clear). Here is the Event enum class from the SDK, with all the defined events.

public enum Event { /** * Constant for onCreate event of the {@link LifecycleOwner}. */ ON_CREATE, /** * Constant for onStart event of the {@link LifecycleOwner}. */ ON_START, /** * Constant for onResume event of the {@link LifecycleOwner}. */ ON_RESUME, /** * Constant for onPause event of the {@link LifecycleOwner}. */ ON_PAUSE, /** * Constant for onStop event of the {@link LifecycleOwner}. */ ON_STOP, /** * Constant for onDestroy event of the {@link LifecycleOwner}. */ ON_DESTROY, /** * An {@link Event Event} constant that can be used to match all events. */ ON_ANY } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public enum Event { /** * Constant for onCreate event of the {@link LifecycleOwner}. */ ON_CREATE , /** * Constant for onStart event of the {@link LifecycleOwner}. */ ON_START , /** * Constant for onResume event of the {@link LifecycleOwner}. */ ON_RESUME , /** * Constant for onPause event of the {@link LifecycleOwner}. */ ON_PAUSE , /** * Constant for onStop event of the {@link LifecycleOwner}. */ ON_STOP , /** * Constant for onDestroy event of the {@link LifecycleOwner}. */ ON_DESTROY , /** * An {@link Event Event} constant that can be used to match all events. */ ON _ ANY }

State

State is as the name says, current state in which the component is. For example, when onCreate is called the component is in CREATED state, when onStart is called it is in STARTED state. Here is the State enum from SDK.

public enum State { /** * Destroyed state for a LifecycleOwner. After this event, this Lifecycle will not dispatch * any more events. For instance, for an {@link android.app.Activity}, this state is reached * <b>right before</b> Activity's {@link android.app.Activity#onDestroy() onDestroy} call. */ DESTROYED, /** * Initialized state for a LifecycleOwner. For an {@link android.app.Activity}, this is * the state when it is constructed but has not received * {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} yet. */ INITIALIZED, /** * Created state for a LifecycleOwner. For an {@link android.app.Activity}, this state * is reached in two cases: * <ul> * <li>after {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} call; * <li><b>right before</b> {@link android.app.Activity#onStop() onStop} call. * </ul> */ CREATED, /** * Started state for a LifecycleOwner. For an {@link android.app.Activity}, this state * is reached in two cases: * <ul> * <li>after {@link android.app.Activity#onStart() onStart} call; * <li><b>right before</b> {@link android.app.Activity#onPause() onPause} call. * </ul> */ STARTED, /** * Resumed state for a LifecycleOwner. For an {@link android.app.Activity}, this state * is reached after {@link android.app.Activity#onResume() onResume} is called. */ RESUMED; /** * Compares if this State is greater or equal to the given {@code state}. * * @param state State to compare with * @return true if this State is greater or equal to the given {@code state} */ public boolean isAtLeast(@NonNull State state) { return compareTo(state) >= 0; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public enum State { /** * Destroyed state for a LifecycleOwner. After this event, this Lifecycle will not dispatch * any more events. For instance, for an {@link android.app.Activity}, this state is reached * <b>right before</b> Activity's {@link android.app.Activity#onDestroy() onDestroy} call. */ DESTROYED , /** * Initialized state for a LifecycleOwner. For an {@link android.app.Activity}, this is * the state when it is constructed but has not received * {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} yet. */ INITIALIZED , /** * Created state for a LifecycleOwner. For an {@link android.app.Activity}, this state * is reached in two cases: * <ul> * <li>after {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} call; * <li><b>right before</b> {@link android.app.Activity#onStop() onStop} call. * </ul> */ CREATED , /** * Started state for a LifecycleOwner. For an {@link android.app.Activity}, this state * is reached in two cases: * <ul> * <li>after {@link android.app.Activity#onStart() onStart} call; * <li><b>right before</b> {@link android.app.Activity#onPause() onPause} call. * </ul> */ STARTED , /** * Resumed state for a LifecycleOwner. For an {@link android.app.Activity}, this state * is reached after {@link android.app.Activity#onResume() onResume} is called. */ RESUMED ; /** * Compares if this State is greater or equal to the given {@code state}. * * @param state State to compare with * @return true if this State is greater or equal to the given {@code state} */ public boolean isAtLeast ( @ NonNull State state ) { return compareTo ( state ) >= 0 ; } }

You can see there is a function named isAtLeast which returns a boolean. So if the current state is CREATED and you want to check if the component has started, then you will call isAtLeast(State.STARTED) which in this case will return false .

Below is an image from official docs that shows Event and State.





Let’s code lifecycle

Now lets see Lifecycle in action. Code along with me!

Open a project and create an empty activity. As I mentioned earlier, to observe lifecycle events emitted by LifecycleObserver we will have to implement an interface named LifecycleObserver. Here is the interface definition from the SDK.

/** * Marks a class as a LifecycleObserver. It does not have any methods, instead, relies on * {@link OnLifecycleEvent} annotated methods. * <p> * @see Lifecycle Lifecycle - for samples and usage patterns. */ @SuppressWarnings("WeakerAccess") public interface LifecycleObserver { } 1 2 3 4 5 6 7 8 9 10 /** * Marks a class as a LifecycleObserver. It does not have any methods, instead, relies on * {@link OnLifecycleEvent} annotated methods. * <p> * @see Lifecycle Lifecycle - for samples and usage patterns. */ @ SuppressWarnings ( "WeakerAccess" ) public interface LifecycleObserver { }

The interface contains no functions :P. So how are you supposed to listen to events? We will do that using annotations. Lets create a class named CustomObserver which will implement LifecycleObserver . Lets listen to the onCreate event of the activity, in the class create a method and name it whatever you want, I will name it…….onCreateEvent and annotate it with @OnLifecycleEvent . In the annotation you specify which event you want to listen to, so we will pass Lifecycle.Event.ON_CREATE in the annotation.

class CustomObserver implements LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) public void onCreateEvent() { Log.d("TAG", "ON_CREATE has been emitted"); } } 1 2 3 4 5 6 class CustomObserver implements LifecycleObserver { @ OnLifecycleEvent ( Lifecycle . Event . ON_CREATE ) public void onCreateEvent ( ) { Log . d ( "TAG" , "ON_CREATE has been emitted" ) ; } }

You can write as many functions you want and listen to as many events you want as many times you want.

Now we need to register this LifecycleObserver to the LifecycleOwner so that we can listen to the events. Now before doing that, you might be wondering, where does this LifecycleOwner comes from??? Remember I told you that Activity and Fragment already provide an implementation of LifecycleOwner .

If you go up the inheritance level of AppCompatActivity till you find SupportActivity , You can see that SupportActivity implements LifecycleOwner.

public class SupportActivity extends Activity implements LifecycleOwner { ... } 1 2 3 public class SupportActivity extends Activity implements LifecycleOwner { . . . }

Here is the LifecycleOwner interface from SDK containing only one method, getLifecycle() which in turn returns an object of Lifecycle .

public interface LifecycleOwner { /** * Returns the Lifecycle of the provider. * * @return The lifecycle of the provider. */ @NonNull Lifecycle getLifecycle(); } 1 2 3 4 5 6 7 8 9 public interface LifecycleOwner { /** * Returns the Lifecycle of the provider. * * @return The lifecycle of the provider. */ @ NonNull Lifecycle getLifecycle ( ) ; }

If you dig deep and look into Lifecycle you can see that it is an abstract class containing various methods and the Event and Status enum classes that we talked about earlier (I have removed all the doc comments for the sake of simplicity). One of the method you can see is addObserver() which takes a LifecycleObserver as a parameter. This is exactly what we are looking for. We will register our CustomObserver using this function.

public abstract class Lifecycle { @MainThread public abstract void addObserver(@NonNull LifecycleObserver observer); @MainThread public abstract void removeObserver(@NonNull LifecycleObserver observer); @MainThread public abstract State getCurrentState(); @SuppressWarnings("WeakerAccess") public enum Event { ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY, ON_ANY } @SuppressWarnings("WeakerAccess") public enum State { DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED; public boolean isAtLeast(@NonNull State state) { return compareTo(state) >= 0; } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public abstract class Lifecycle { @ MainThread public abstract void addObserver ( @ NonNull LifecycleObserver observer ) ; @ MainThread public abstract void removeObserver ( @ NonNull LifecycleObserver observer ) ; @ MainThread public abstract State getCurrentState ( ) ; @ SuppressWarnings ( "WeakerAccess" ) public enum Event { ON_CREATE , ON_START , ON_RESUME , ON_PAUSE , ON_STOP , ON_DESTROY , ON _ ANY } @ SuppressWarnings ( "WeakerAccess" ) public enum State { DESTROYED , INITIALIZED , CREATED , STARTED , RESUMED ; public boolean isAtLeast ( @ NonNull State state ) { return compareTo ( state ) >= 0 ; } } }

Now in the onCreate of your activity get the Lifecycle by calling getLifecycle() and add the object of your new observer by calling addObserver.

getLifecycle().addObserver(new CustomObserver()); 1 getLifecycle ( ) . addObserver ( new CustomObserver ( ) ) ;

Run your application and check the logs. Experiment more with this LifecycleObserver class.

You can also implement your custom LifecycleOwner and send events using LifecycleRegistry . It is quite straightforward and explained in the docs here, so I won’t go over it.

Lifecycle Component is a convenient class which lays foundation on understanding the workings of LiveData (which we will take a look at in next tutorial). I would recommend you to now read the docs on Lifecycle.

Get stared with Room Database in Android

Kotlin Data Class Tutorial

Move Content to side while swiping in Navigation Drawer

Using Fonts in Android