AndroidX : Mastering JetPack Lifecycle.
Efficiently manage Android component lifecycles with AndroidX Lifecycle Library, using key concepts and practical examples for cleaner architecture.
The AndroidX Lifecycle library is part of Jetpack and helps manage the lifecycle of Android components like activities and fragments. It simplifies handling lifecycle events and makes our app's components lifecycle-aware.
Key Components and Concepts
LifecycleOwner: An interface that indicates an object has an Android lifecycle. Activities and fragments are the primary implementations.
LifecycleObserver: An interface for classes that want to observe the lifecycle of
LifecycleOwner
components. Observer classes use annotations like@OnLifecycleEvent
to indicate which lifecycle events they are interested in.Lifecycle: A class that holds information about the lifecycle state of a component (like an activity or fragment). It can be used to query the current state and add/remove observers.
Lifecycle.Event: Enumerates different lifecycle events (e.g.,
ON_CREATE
,ON_START
,ON_RESUME
, etc.).
Lifecycle.State
Lifecycle.State: Enumerates different lifecycle states:
INITIALIZED: The initial state, not yet created.
CREATED: The state after
onCreate
is called.STARTED: The state after
onStart
is called.RESUMED: The state after
onResume
is called.DESTROYED: The state after
onDestroy
is called.
Lifecycle Callbacks
Here are the primary lifecycle callbacks:
ON_CREATE: Called when the
LifecycleOwner
is created.ON_START: Called when the
LifecycleOwner
becomes visible to the user.ON_RESUME: Called when the
LifecycleOwner
starts interacting with the user.ON_PAUSE: Called when the
LifecycleOwner
stops interacting with the user.ON_STOP: Called when the
LifecycleOwner
is no longer visible to the user.ON_DESTROY: Called when the
LifecycleOwner
is destroyed.
How It Works
LifecycleOwner: An
Activity
orFragment
implements theLifecycleOwner
interface. It manages aLifecycleRegistry
object, which tracks the lifecycle state and events.LifecycleRegistry: This is an implementation of
Lifecycle
used byLifecycleOwner
to handle lifecycle events and states.LifecycleObserver: You can create classes that implement
LifecycleObserver
to observe lifecycle changes. These classes can define methods annotated with@OnLifecycleEvent
to receive lifecycle callbacks.
Implementing LifecycleOwner
The LifecycleOwner
interface is implemented in the ComponentActivity
class, which is the base class for activities in the AndroidX library. ComponentActivity
extends Activity
and implements LifecycleOwner
.
Here's a simplified view of how LifecycleOwner
is implemented in ComponentActivity
:
LifecycleOwner Interface
public interface LifecycleOwner {
Lifecycle getLifecycle();
}
ComponentActivity Implementation
In ComponentActivity
, the lifecycle is managed by a LifecycleRegistry
object:
public class ComponentActivity extends Activity implements LifecycleOwner {
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
}
@Override
protected void onStart() {
super.onStart();
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
}
@Override
protected void onResume() {
super.onResume();
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
}
@Override
protected void onPause() {
super.onPause();
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
}
@Override
protected void onStop() {
super.onStop();
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
}
@Override
protected void onDestroy() {
super.onDestroy();
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
}
}
LifecycleRegistry
LifecycleRegistry
is a key part of the AndroidX Lifecycle library. It manages the lifecycle events of LifecycleOwner
objects like Activity
or Fragment
. It keeps a list of observers who are informed about lifecycle changes and tracks the current lifecycle state.
Key Features of LifecycleRegistry
Lifecycle Management: It tracks the current state of the lifecycle and transitions through various lifecycle states.
Observer Notifications: Notifies registered
LifecycleObserver
instances of lifecycle events.State Handling: Handles the progression of lifecycle states and events in a controlled manner.
Internal Implementation
Here's a simplified version of how LifecycleRegistry
works internally:
public class LifecycleRegistry extends Lifecycle {
private State mState;
private final WeakReference<LifecycleOwner> mLifecycleOwner;
private final FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap = new FastSafeIterableMap<>();
public LifecycleRegistry(@NonNull LifecycleOwner provider) {
mLifecycleOwner = new WeakReference<>(provider);
mState = State.INITIALIZED;
}
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
ObserverWithState statefulObserver = new ObserverWithState(observer, mState);
mObserverMap.putIfAbsent(observer, statefulObserver);
}
@Override
public void removeObserver(@NonNull LifecycleObserver observer) {
mObserverMap.remove(observer);
}
@Override
public State getCurrentState() {
return mState;
}
public void handleLifecycleEvent(@NonNull Event event) {
mState = event.getTargetState();
for (Entry<LifecycleObserver, ObserverWithState> entry : mObserverMap) {
entry.getValue().dispatchEvent(mLifecycleOwner.get(), event);
}
}
static class ObserverWithState {
State mState;
LifecycleObserver mObserver;
ObserverWithState(LifecycleObserver observer, State initialState) {
mObserver = observer;
mState = initialState;
}
void dispatchEvent(LifecycleOwner owner, Event event) {
// Dispatch event to the observer
}
}
}
Explanation
State Management:
mState
represents the current state of the lifecycle (e.g.,CREATED
,STARTED
).The
handleLifecycleEvent
method updates this state based on lifecycle events.
Observer Management:
mObserverMap
stores the observers along with their respective states.addObserver
andremoveObserver
methods manage the observers, adding or removing them frommObserverMap
.
Lifecycle Event Handling:
handleLifecycleEvent
method is called whenever a lifecycle event occurs. It:Updates the current state.
Notifies each observer by calling
dispatchEvent
on theObserverWithState
instance.
WeakReference:
mLifecycleOwner
is held as aWeakReference
to prevent memory leaks by allowing theLifecycleOwner
to be garbage collected when it is no longer in use.
ObserverWithState Class:
Holds the state and the observer itself.
dispatchEvent
method is responsible for invoking the appropriate callback methods on the observer when lifecycle events occur.
Example
Step 1: Add Dependencies
Add the necessary dependencies in our build.gradle
file:
dependencies {
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
}
Step 2: Create a LifecycleObserver
Create a class that implements LifecycleObserver
and define methods to handle lifecycle events:
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
class MyObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreateEvent() {
println("ON_CREATE event")
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onStartEvent() {
println("ON_START event")
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onResumeEvent() {
println("ON_RESUME event")
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun onPauseEvent() {
println("ON_PAUSE event")
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onStopEvent() {
println("ON_STOP event")
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroyEvent() {
println("ON_DESTROY event")
}
}
Step 3: Attach the Observer to a LifecycleOwner
Attach our LifecycleObserver
to a LifecycleOwner
(e.g., an Activity
or Fragment
):
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private lateinit var myObserver: MyObserver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
myObserver = MyObserver()
lifecycle.addObserver(myObserver)
}
}
Advantages
Separation of Concerns: Move lifecycle-dependent code out of
Activity
orFragment
classes into separate, reusable components.Simplified Lifecycle Management: Lifecycle-aware components automatically handle lifecycle events and state transitions, reducing boilerplate code.
Cleaner Architecture: Promotes a cleaner architecture by decoupling lifecycle-related logic from UI logic.
Summary
LifecycleOwner: Interface that any class with a lifecycle (like
Activity
orFragment
) should implement. It provides agetLifecycle
method.LifecycleRegistry: A concrete implementation of
Lifecycle
used internally byLifecycleOwner
to manage the lifecycle events and states.ComponentActivity: Extends
Activity
and implementsLifecycleOwner
. It initializes aLifecycleRegistry
and handles lifecycle events.LifecycleObserver: An interface for classes that want to observe lifecycle changes. Methods in these classes are annotated with
@OnLifecycleEvent
.
Conclusion
The AndroidX Lifecycle library, part of Jetpack, provides a robust framework for managing the lifecycle of Android components like activities and fragments. By implementing the LifecycleOwner
interface and using the LifecycleRegistry
, ComponentActivity
and other components can efficiently handle lifecycle events. Observers implementing LifecycleObserver
can be easily attached to monitor these events, promoting a clean separation of concerns, simplifying lifecycle management, and enhancing the overall architecture of our application. This approach reduces boilerplate code and makes our application more maintainable and scalable.
That's it for today. Happy Coding...