AndroidX : Mastering JetPack Lifecycle.

AndroidX : Mastering JetPack Lifecycle.

Efficiently manage Android component lifecycles with AndroidX Lifecycle Library, using key concepts and practical examples for cleaner architecture.

ยท

6 min read

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

  1. LifecycleOwner: An Activity or Fragment implements the LifecycleOwner interface. It manages a LifecycleRegistry object, which tracks the lifecycle state and events.

  2. LifecycleRegistry: This is an implementation of Lifecycle used by LifecycleOwner to handle lifecycle events and states.

  3. 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

  1. Lifecycle Management: It tracks the current state of the lifecycle and transitions through various lifecycle states.

  2. Observer Notifications: Notifies registered LifecycleObserver instances of lifecycle events.

  3. 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

  1. State Management:

    • mState represents the current state of the lifecycle (e.g., CREATED, STARTED).

    • The handleLifecycleEvent method updates this state based on lifecycle events.

  2. Observer Management:

    • mObserverMap stores the observers along with their respective states.

    • addObserver and removeObserver methods manage the observers, adding or removing them from mObserverMap.

  3. Lifecycle Event Handling:

    • handleLifecycleEvent method is called whenever a lifecycle event occurs. It:

      • Updates the current state.

      • Notifies each observer by calling dispatchEvent on the ObserverWithState instance.

  4. WeakReference:

    • mLifecycleOwner is held as a WeakReference to prevent memory leaks by allowing the LifecycleOwner to be garbage collected when it is no longer in use.
  5. 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 or Fragment 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

  1. LifecycleOwner: Interface that any class with a lifecycle (like Activity or Fragment) should implement. It provides a getLifecycle method.

  2. LifecycleRegistry: A concrete implementation of Lifecycle used internally by LifecycleOwner to manage the lifecycle events and states.

  3. ComponentActivity: Extends Activity and implements LifecycleOwner. It initializes a LifecycleRegistry and handles lifecycle events.

  4. 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...

ย