Android basics 01
Android Lifecycle-Aware Components
1. The Problem with Traditional Lifecycle Management
In standard Android development, asynchronous or dependent operations (like fetching user location, downloading images, or running video players) are typically started and stopped directly within the activity’s or fragment’s lifecycle callback methods (e.g., onCreate(), onStart(), onResume(), onPause(), onStop()).
The Drawbacks:
- Fat/Bloated Components: Activities and fragments end up handling too many responsibilities (tightly coupled logic) when their primary duty should only be rendering UI and managing direct user interactions.
- Code Duplication: If multiple activities need the same lifecycle-dependent logic, you have to copy-paste the setup and teardown code across them.
- Race Conditions / Memory Leaks: If an operation initializes or stops a fraction of a second too late due to tight coupling in the Activity callbacks, it can cause the app to crash or leak memory.
2. What are Lifecycle-Aware Components?
Lifecycle-aware components are architectural pieces that can monitor the lifecycle status of another component (like an Activity or a Fragment) and automatically adjust their behavior based on that state without the Activity explicitly telling them to.
Get Rohan Vishwakarma’s stories in your inbox
Join Medium for free to get updates from this writer.
It works on an Observer Pattern built around two key abstractions:
- Lifecycle Owner (
LifecycleOwner): An interface implemented by components that have a lifecycle (e.g.,AppCompatActivity,Fragment). They hold aLifecycleobject and emit events when their state changes. - Lifecycle Observer (
DefaultLifecycleObserver/LifecycleObserver): An interface implemented by any class that needs to monitor aLifecycleOwner. It receives notifications when the owner changes state.
3. Order of Lifecycle Execution
An important architectural nuance highlighted in the video is the execution order of callbacks between the Owner (Activity) and the Observer during different phases:
- Creation Phase (
onCreate,onStart,onResume): The Activity callbacks run first, followed by the Observer callbacks. (Logic: The Activity must exist or be visible before the observer can safety hook into its state). - Destruction Phase (
onPause,onStop,onDestroy): The Observer callbacks run first, followed by the Activity callbacks. (Logic: The background operations must clean up/teardown safely before the Activity destroys itself).
4. Implementation Code Snippets
Here is how you extract lifecycle code out of an Activity and place it cleanly into an independent Observer class.
Step 1: Create the Lifecycle Observer
We create a separate class that implements DefaultLifecycleObserver. By using the @OnLifecycleEvent annotation (or implementing the interface functions), we map our functions to specific Android lifecycle events.
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import android.util.Log
// This class is completely independent and handles its own lifecycle actions
class MyVideoPlayerObserver : DefaultLifecycleObserver {
private val TAG = "MyVideoPlayerObserver"
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
Log.d(TAG, "Observer: ON_CREATE - Initializing Video Player configurations")
}
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
Log.d(TAG, "Observer: ON_RESUME - Play/Resume Video")
}
override fun onPause(owner: LifecycleOwner) {
super.onPause(owner)
Log.d(TAG, "Observer: ON_PAUSE - Pausing Video playback to save resources")
}
override fun onStop(owner: LifecycleOwner) {
super.onStop(owner)
Log.d(TAG, "Observer: ON_STOP - Releasing Video Player resources")
}
}Step 2: Register the Observer in the Activity
In your Activity (which inherently acts as the LifecycleOwner), you simply instantiate your custom observer class and attach it to the activity's lifecycle instance using lifecycle.addObserver().
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d(TAG, "Activity: onCreate")
// 1. Create an instance of your custom observer
val videoPlayerObserver = MyVideoPlayerObserver()
// 2. Attach the observer to this Activity's lifecycle
lifecycle.addObserver(videoPlayerObserver)
}
override fun onResume() {
super.onResume()
Log.d(TAG, "Activity: onResume")
}
override fun onPause() {
super.onPause()
Log.d(TAG, "Activity: onPause")
}
}5. Summary of Benefits
- Reusability: The
MyVideoPlayerObserverclass is now 100% decoupled. You can drop this exact same observer into aSecondaryActivityor aDetailFragmentusing a single line of code (lifecycle.addObserver()). - Lean Activities: The Activity doesn’t need blocks of video-player initialization or pausing logic cluttering up its code.
- Easier Maintenance: If there is a bug with how background tasks handle app minimization, you know exactly which isolated observer file to look at.






