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 Kotlin.
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 -> kotlin+java -> com.ebookfrenzy.lifecycledemo in the Project tool window and select New -> Kotlin Class/File… from the resulting menu. In the New Class dialog, name the class DemoObserver, select Class from the list, and press the keyboard Return key to create the DemoObserver.kt file. The new file should automatically open in the editor, where it will read as follows:
package com.ebookfrenzy.lifecycledemo
class DemoObserver {
}
Code language: Kotlin (kotlin)
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
class DemoObserver: DefaultLifecycleObserver {
}
Code language: Kotlin (kotlin)
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.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
class DemoObserver: DefaultLifecycleObserver {
private val TAG = "DemoObserver"
override fun onCreate(owner: LifecycleOwner) {
Log.i(TAG, "onCreate")
}
override fun onResume(owner: LifecycleOwner) {
Log.i(TAG, "onResume")
}
override fun onPause(owner: LifecycleOwner) {
Log.i(TAG, "onPause")
}
override fun onStart(owner: LifecycleOwner) {
Log.i(TAG, "onStart")
}
override fun onStop(owner: LifecycleOwner) {
Log.i(TAG, "onStop")
}
override fun onDestroy(owner: LifecycleOwner) {
Log.i(TAG, "onDestroy")
}
}
Code language: Kotlin (kotlin)
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.kt class file and edit the onCreate() method to add an observer:
.
.
import com.ebookfrenzy.lifecycledemo.DemoObserver
.
.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycle.addObserver(DemoObserver())
}
Code language: Kotlin (kotlin)
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 Tutorial, 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 -> kotlin+java -> com.ebookfrenzy.lifecycledemo entry in the Project tool window and selecting the New -> Kotlin Class/File… menu option. Name the class DemoOwner in the Create Class dialog and select the Class option before tapping the keyboard Return key. With the new DemoOwner.kt 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
class DemoOwner: LifecycleOwner(override val lifecycle: Lifecycle) {
}
Code language: Kotlin (kotlin)
TThe 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 and a constructor to initialize the LifecycleRegistry instance:
package com.ebookfrenzy.lifecycledemo
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
class DemoOwner(override val lifecycle: Lifecycle): LifecycleOwner {
private val lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this)
init {
}
}
Code language: Kotlin (kotlin)
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:
.
.
fun startOwner() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)
}
fun stopOwner() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
}
.
.
Code language: Kotlin (kotlin)
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 to the class constructor:
init {
lifecycle.addObserver(DemoObserver())
}
Code language: Kotlin (kotlin)
Load the MainActivity.kt 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 lateinit var demoOwner: DemoOwner
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
demoOwner = DemoOwner(this.lifecycle)
demoOwner.startOwner()
demoOwner.stopOwner()
}
Code language: Kotlin (kotlin)
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
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.