The previous chapter provided an overview of lifecycle awareness and outlined the key classes and interfaces that make this possible within an Android app project. This chapter will build on this knowledge base by building an Android Studio project to highlight lifecycle awareness in action.
Creating the Example Lifecycle Project
Select the New Project quick start option from the welcome screen and, within the resulting new project dialog, choose the Empty Views Activity template before clicking on the Next button.
Enter LifecycleDemo into the Name field and specify com.ebookfrenzy.lifecycledemo as the package name. Before clicking on the Finish button, change the Minimum API level setting to API 26: Android 8.0 (Oreo) and the Language menu to Java.
Creating a Lifecycle Observer
As previously discussed, activities and fragments already implement the LifecycleOwner interface and are ready to be observed by other objects. To see this in practice, the next step in this tutorial is to add a new class to the project that will be able to observe the MainActivity instance.
To add the new class, right-click on app -> java -> com.ebookfrenzy.lifecycledemo in the Project tool window and select New -> Java Class… from the resulting menu. In the New Class dialog, name the class DemoObserver and press the keyboard Return key to create the DemoObserver.java file. The new file should automatically open in the editor, where it will read as follows:
package com.ebookfrenzy.lifecycledemo;
public class DemoObserver {
}
Code language: Java (java)
Remaining in the editor, modify the class file to declare that it will be implementing the DefaultLifecycleObserver interface:
package com.ebookfrenzy.lifecycledemo;
import androidx.lifecycle.DefaultLifecycleObserver;
public class DemoObserver implements DefaultLifecycleObserver {
Code language: Java (java)
The next step is to override the lifecycle methods of the DefaultLifecycleObserver class. For this example, all events will be handled, each outputting a message to the Logcat panel displaying the event type. Update the observer class as outlined in the following listing:
package com.ebookfrenzy.lifecycledemo;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
.
.
public class DemoObserver implements DefaultLifecycleObserver {
private String LOG_TAG = "DemoObserver";
@Override
public void onCreate(@NonNull LifecycleOwner owner) {
Log.i(LOG_TAG, "onCreate");
}
@Override
public void onResume(@NonNull LifecycleOwner owner) {
Log.i(LOG_TAG, "onResume");
}
@Override
public void onPause(@NonNull LifecycleOwner owner) {
Log.i(LOG_TAG, "onPause");
}
@Override
public void onStart(@NonNull LifecycleOwner owner) {
Log.i(LOG_TAG, "onStart");
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
Log.i(LOG_TAG, "onStop");
}
@Override
public void onDestroy(@NonNull LifecycleOwner owner) {
Log.i(LOG_TAG, "onDestroy");
}
}
Code language: Java (java)
With the DemoObserver class completed, the next step is to add it as an observer on the MainActivity class.
Adding the Observer
Observers are added to lifecycle owners via calls to the addObserver() method of the owner’s Lifecycle object, a reference to which is obtained via a call to the getLifecycle() method. Edit the MainActivity.java class file and edit the onCreate() method to add an observer:
.
.
import com.ebookfrenzy.lifecycledemo.DemoObserver;
.
.
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getLifecycle().addObserver(new DemoObserver());
}
Code language: Java (java)
With the observer class created and added to the lifecycle owner’s Lifecycle object, the app is ready to be tested.
Testing the Observer
Since the DemoObserver class outputs diagnostic information to the Logcat console, it will be easier to see the output if a filter is configured to display only the DemoObserver messages. Using the steps outlined previously in Android Activity State Changes, display the Logcat panel and enter the following keys into the filter field:
package:mine tag:DemoObserver
Code language: plaintext (plaintext)
On successful launch of the app, the Logcat output should indicate the following lifecycle state changes and events:
onCreate
onStart
onResume
Code language: plaintext (plaintext)
With the app still running, perform a device rotation to trigger the destruction and recreation of the activity, generating the following additional output:
onPause
onStop
onDestroy
onCreate
onStart
onResume
Code language: plaintext (plaintext)
Before moving to the next section in this chapter, take some time to compare the output from the app with the flow chart in Figure 45-2 of the previous chapter.
Creating a Lifecycle Owner
The final task in this chapter is to create a custom lifecycle owner class and demonstrate how to trigger events and modify the lifecycle state from within that class.
Add a new class by right-clicking on the app -> java -> com.ebookfrenzy.lifecycledemo entry in the Project tool window and selecting the New -> Java Class… menu option. Name the class DemoOwner in the Create Class dialog before tapping the keyboard Return key. With the new DemoOwner.java file loaded into the code editor, modify it as follows:
package com.ebookfrenzy.lifecycledemo;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
import androidx.annotation.NonNull;
public class DemoOwner implements LifecycleOwner {
}
Code language: Java (java)
The class will need a LifecycleRegistry instance initialized with a reference to itself and a getLifecycle() method configured to return the LifecycleRegistry instance. Declare a variable to store the LifecycleRegistry reference, a constructor to initialize the LifecycleRegistry instance, and add the getLifecycle() method:
public class DemoOwner implements LifecycleOwner {
private final LifecycleRegistry lifecycleRegistry;
public DemoOwner() {
lifecycleRegistry = new LifecycleRegistry(this);
}
@NonNull
@Override
public Lifecycle getLifecycle() {
return lifecycleRegistry;
}
}
Code language: Java (java)
Next, the class must notify the registry of lifecycle state changes. This can be achieved by marking the state with the markState() method of the LifecycleRegistry object or by triggering lifecycle events using the handleLifecycleEvent() method. What constitutes a state change within a custom class will depend on the purpose of the class. For this example, we will add some methods that trigger lifecycle events when called:
.
.
private final LifecycleRegistry lifecycleRegistry;
.
.
public void startOwner() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
}
public void stopOwner() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
}
@NonNull
@Override
public Lifecycle getLifecycle() {
return lifecycleRegistry;
}
.
.
Code language: Java (java)
The last change within the DemoOwner class is to add the DemoObserver class as the observer. This call will be made by adding the following constructor to the class:
public DemoOwner() {
lifecycleRegistry = new LifecycleRegistry(this);
getLifecycle().addObserver(new DemoObserver());
}
Code language: Java (java)
Load the MainActivity.java file into the code editor, locate the onCreate() method, and add code to create an instance of the DemoOwner class and to call the startOwner() and stopOwner() methods. Note also that the call to add the DemoObserver as an observer has been removed. Although a single observer can be used with multiple owners, it is removed in this case to avoid duplicated and confusing output within the Logcat tool window:
.
.
import com.ebookfrenzy.lifecycledemo.DemoOwner;
.
.
private DemoOwner demoOwner;
.
.
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
demoOwner = new DemoOwner();
demoOwner.startOwner();
demoOwner.stopOwner();
getLifecycle().addObserver(new DemoObserver());
}
Code language: Java (java)
Testing the Custom Lifecycle Owner
Build and run the app one final time, refer to the Logcat tool window, and confirm that the observer detected the create, start, and stop lifecycle events in the following order:
onCreate
onStart
onStop
Code language: plaintext (plaintext)
Note that the “created” state changes were triggered even though code was not added to the DemoOwner class to do this manually. These were triggered automatically when the owner instance was first created and when the ON_STOP event was handled.
Summary
This chapter has provided a practical demonstration of implementing lifecycle awareness within an Android app, including creating a lifecycle observer and designing and implementing a basic lifecycle owner class.