Lifecycle-Aware components are part of Android Jetpack, which can sense changes in the lifecycle state of Activities and Fragments, facilitating the generation of more organized, lightweight, and maintainable code. A common development approach is to handle related business logic in the corresponding lifecycle methods of the components. This approach can lead to poor code quality and an increase in bugs. By using lifecycle components, the code that depends on the lifecycle can be removed from the lifecycle and moved into the component itself.
- Lifecycle
- Lifecycle Source Code Analysis
- Initialization of ProcessLifecycleOwner
Lifecycle#
Lifecycle is an abstract class that holds lifecycle state information for components. Its direct subclass is LifecycleRegistry. Both Activity and Fragment indirectly implement the LifecycleOwner interface and provide the corresponding getLifecycle method to obtain the Lifecycle object, which is actually the LifecycleRegistry object. Below is the state diagram corresponding to the Lifecycle's lifecycle:
The diagram mainly highlights two points: Event and Status.
- Event: Such as ON_CREATE, ON_START, etc., corresponding to the lifecycle methods of Activity or Fragment.
- Status: The state in which the lifecycle is located within Lifecycle, such as the next state after ON_CREATE and ON_STOP is the CREATED state. Based on the diagram, specific lifecycle events can be mapped to their corresponding states.
If the development environment is Java 1.7, you can use annotations to listen for lifecycle changes, as shown below:
/**
* Powered by jzman.
* Created on 2018/12/8 0008.
*/
public class LifeCycleListener implements LifecycleObserver {
private static final String TAG = LifeCycleListener.class.getSimpleName();
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
private void onCreate(LifecycleOwner owner) {
Log.i(TAG,"--onCreate-->");
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
private void onStart(LifecycleOwner owner) {
Log.i(TAG,"--onStart-->");
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
private void onResume(LifecycleOwner owner) {
Log.i(TAG,"--onResume-->");
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
private void onPause(LifecycleOwner owner) {
Log.i(TAG,"--onPause-->");
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
private void onStop(LifecycleOwner owner) {
Log.i(TAG,"--onStop-->");
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
private void onDestroy(LifecycleOwner owner) {
Log.i(TAG,"--onDestroy-->");
}
@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
private void onAny(LifecycleOwner owner, Lifecycle.Event event) {
// The onAny method can add a second parameter to get the current lifecycle
// Any change in lifecycle state will trigger this
Log.i(TAG,"--onAny-->"+event.name());
}
}
If the development environment is Java 1.8, it is recommended to use the implementation of the DefaultLifecycleObserver interface to listen for lifecycle changes. First, include the following in the corresponding module's build.gradle file:
implementation "android.arch.lifecycle:common-java8:1.1.1"
Then, create the lifecycle listener as follows:
/**
* Powered by jzman.
* Created on 2018/12/10 0010.
*/
public class LifeCycleListener1 implements DefaultLifecycleObserver {
private static final String TAG = LifeCycleListener.class.getSimpleName();
@Override
public void onCreate(@NonNull LifecycleOwner owner) {
Log.i(TAG,"--onCreate-->");
}
@Override
public void onStart(@NonNull LifecycleOwner owner) {
Log.i(TAG,"--onStart-->");
}
@Override
public void onResume(@NonNull LifecycleOwner owner) {
Log.i(TAG,"--onResume-->");
}
@Override
public void onPause(@NonNull LifecycleOwner owner) {
Log.i(TAG,"--onPause-->");
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
Log.i(TAG,"--onStop-->");
}
@Override
public void onDestroy(@NonNull LifecycleOwner owner) {
Log.i(TAG,"--onDestroy-->");
}
}
Finally, register this listener in the corresponding Activity or Fragment, as shown below:
LifeCycleListener mLifeCycleListener = new LifeCycleListener();
getLifecycle().addObserver(mLifeCycleListener);
Taking LifeCycleListener as an example, the lifecycle listening logs for Activity are as follows:
// Open Activity
--onCreate-->
--onAny-->ON_CREATE
--onStart-->
--onAny-->ON_START
--onResume-->
--onAny-->ON_RESUME
// Exit Activity
--onPause-->
--onAny-->ON_PAUSE
--onStop-->
--onAny-->ON_STOP
--onDestroy-->
--onAny-->ON_DESTROY
Lifecycle Source Code Analysis#
LifecycleOwner is an interface that indicates that the class implementing it has a lifecycle. For example, all Activities that inherit from AppCompatActivity indirectly implement the LifecycleOwner interface. In the source code, it is the ComponentActivity that implements this interface. In actual development, you can implement the LifecycleOwner interface to move the business logic originally executed in the Activity or Fragment lifecycle into the component itself.
From the above, it can be seen that using getLifecycle() retrieves the specific implementation class of Lifecycle, which is the LifecycleRegistry object. Then, using addObserver adds the LifecycleObserver object, which is to add the observers to be notified. Only then can the observers be notified when the lifecycle of the Activity or Fragment changes. So how is the Activity's lifecycle perceived?
In ComponentActivity, a non-UI Fragment is added to sense the Activity's lifecycle. The source code is as follows:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSavedStateRegistryController.performRestore(savedInstanceState);
// Add a Fragment in the Activity
ReportFragment.injectIfNeededIn(this);
}
The injectIfNeededIn method creates a Fragment named ReportFragment. Each time an Activity is created, this Fragment will be added to the corresponding Activity. The source code for ReportFragment is as follows:
public class ReportFragment extends Fragment {
// Create Fragment
public static void injectIfNeededIn(Activity activity) {
android.app.FragmentManager manager = activity.getFragmentManager();
// Ensure it is added only once
if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
manager.executePendingTransactions();
}
}
//...
// Initialize listener for Activity, listening to Activity's lifecycle state
private ActivityInitializationListener mProcessListener;
// Dispatch Activity lifecycle state
private void dispatchCreate(ActivityInitializationListener listener) {
if (listener != null) {
listener.onCreate();
}
}
private void dispatchStart(ActivityInitializationListener listener) {
if (listener != null) {
listener.onStart();
}
}
private void dispatchResume(ActivityInitializationListener listener) {
if (listener != null) {
listener.onResume();
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Dispatch corresponding lifecycle state
dispatchCreate(mProcessListener);
dispatch(Lifecycle.Event.ON_CREATE);
}
@Override
public void onStart() {
super.onStart();
dispatchStart(mProcessListener);
dispatch(Lifecycle.Event.ON_START);
}
@Override
public void onResume() {
super.onResume();
dispatchResume(mProcessListener);
dispatch(Lifecycle.Event.ON_RESUME);
}
@Override
public void onPause() {
super.onPause();
dispatch(Lifecycle.Event.ON_PAUSE);
}
@Override
public void onStop() {
super.onStop();
dispatch(Lifecycle.Event.ON_STOP);
}
@Override
public void onDestroy() {
super.onDestroy();
dispatch(Lifecycle.Event.ON_DESTROY);
// Just want to be sure that we won't leak reference to an activity
mProcessListener = null;
}
// Dispatch lifecycle state
private void dispatch(Lifecycle.Event event) {
// The LifecycleRegistryOwner has been deprecated, kept for compatibility
Activity activity = getActivity();
if (activity instanceof LifecycleRegistryOwner) {
((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
return;
}
// Get Lifecycle from Activity
if (activity instanceof LifecycleOwner) {
Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
// Dispatch Activity lifecycle state
((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
}
}
}
void setProcessListener(ActivityInitializationListener processListener) {
mProcessListener = processListener;
}
// Activity initialization listener
interface ActivityInitializationListener {
void onCreate();
void onStart();
void onResume();
}
}
It can be seen that the corresponding lifecycle state is dispatched in the lifecycle methods of ReportFragment. The dispatch process corresponds to the dispatch method, which calls the handleLifecycleEvent method. This method will be introduced later, where the lifecycle listening for the Activity is completed in the ActivityInitializationListener. The implementation class of this interface is an anonymous inner class located in ProcessLifecycleOwner, as shown in the source code below:
public class ProcessLifecycleOwner implements LifecycleOwner {
// ...
private Handler mHandler;
private final LifecycleRegistry mRegistry = new LifecycleRegistry(this);
private Runnable mDelayedPauseRunnable = new Runnable() {
@Override
public void run() {
dispatchPauseIfNeeded();
dispatchStopIfNeeded();
}
};
// Anonymous implementation of ActivityInitializationListener
private ActivityInitializationListener mInitializationListener =
new ActivityInitializationListener() {
@Override
public void onCreate() {
// What?
// Why is there no handling? It doesn't affect reading the source code.
}
@Override
public void onStart() {
activityStarted();
}
@Override
public void onResume() {
activityResumed();
}
};
private static final ProcessLifecycleOwner sInstance = new ProcessLifecycleOwner();
// Initialization, where is it initialized? -> See later sections
static void init(Context context) {
sInstance.attach(context);
}
void activityStarted() {
mStartedCounter++;
if (mStartedCounter == 1 && mStopSent) {
// Whether ON_START or ON_RESUME, the key is still the handleLifecycleEvent method
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
mStopSent = false;
}
}
void activityResumed() {
mResumedCounter++;
if (mResumedCounter == 1) {
if (mPauseSent) {
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
mPauseSent = false;
} else {
mHandler.removeCallbacks(mDelayedPauseRunnable);
}
}
}
void activityPaused() {
mResumedCounter--;
if (mResumedCounter == 0) {
mHandler.postDelayed(mDelayedPauseRunnable, TIMEOUT_MS);
}
}
void activityStopped() {
mStartedCounter--;
dispatchStopIfNeeded();
}
private void dispatchPauseIfNeeded() {
if (mResumedCounter == 0) {
mPauseSent = true;
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
}
}
private void dispatchStopIfNeeded() {
if (mStartedCounter == 0 && mPauseSent) {
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
mStopSent = true;
}
}
void attach(Context context) {
mHandler = new Handler();
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
Application app = (Application) context.getApplicationContext();
// Before there were Lifecycle components, use ActivityLifecycleCallbacks to listen to all Activity lifecycles
app.registerActivityLifecycleCallbacks(new EmptyActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
ReportFragment.get(activity).setProcessListener(mInitializationListener);
}
@Override
public void onActivityPaused(Activity activity) {
activityPaused();
}
@Override
public void onActivityStopped(Activity activity) {
activityStopped();
}
});
}
}
Before there were Lifecycle components, ActivityLifecycleCallbacks was registered in the Application to listen to all Activity lifecycles. Here, ActivityLifecycleCallbacks is also used, but the object being listened to has changed to a single Activity, making it feel more flexible.
Note: There is a question above: how is ProcessLifecycleOwner initialized? The answer will be found in the next section.
From the analysis above, the final lifecycle state dispatch occurs in the handleLifecycleEvent method of LifecycleRegistry, which calls the sync method. The source code is as follows:
private void sync() {
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
Log.w(LOG_TAG, "LifecycleOwner is garbage collected, you shouldn't try dispatch "
+ "new events from it.");
return;
}
while (!isSynced()) {
mNewEventOccurred = false;
// No need to check eldest for nullability, because isSynced does it for us.
if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
backwardPass(lifecycleOwner);
}
Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
if (!mNewEventOccurred && newest != null
&& mState.compareTo(newest.getValue().mState) > 0) {
// Key method
forwardPass(lifecycleOwner);
}
}
mNewEventOccurred = false;
}
Continuing to look at the forwardPass method, the source code is as follows:
private void forwardPass(LifecycleOwner lifecycleOwner) {
Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
mObserverMap.iteratorWithAdditions();
while (ascendingIterator.hasNext() && !mNewEventOccurred) {
Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
ObserverWithState observer = entry.getValue();
while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
&& mObserverMap.contains(entry.getKey()))) {
pushParentState(observer.mState);
// Dispatch lifecycle state
observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
popParentState();
}
}
}
Continuing to look at the dispatchEvent method:
static class ObserverWithState {
State mState;
GenericLifecycleObserver mLifecycleObserver;
ObserverWithState(LifecycleObserver observer, State initialState) {
// Generate the corresponding type of GenericLifecycleObserver based on observer
mLifecycleObserver = Lifecycling.getCallback(observer);
mState = initialState;
}
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
// Callback for lifecycle state
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
}
Following the convention, looking at the implementation class of GenericLifecycleObserver will reveal the flow of the dispatched lifecycle state in the onStateChanged method. The specific implementation of which GenericLifecycleObserver is used depends on the observer passed to the getCallback method. The source code for the getCallback method is as follows:
@NonNull
static GenericLifecycleObserver getCallback(Object object) {
// Directly inherits DefaultLifecycleObserver
if (object instanceof FullLifecycleObserver) {
return new FullLifecycleObserverAdapter((FullLifecycleObserver) object);
}
// Presumably: If the custom Observer inherits from GenericLifecycleObserver while managing the lifecycle
if (object instanceof GenericLifecycleObserver) {
return (GenericLifecycleObserver) object;
}
// Uses annotation processor
final Class<?> klass = object.getClass();
int type = getObserverConstructorType(klass);
if (type == GENERATED_CALLBACK) {
List<Constructor<? extends GeneratedAdapter>> constructors =
sClassToAdapters.get(klass);
if (constructors.size() == 1) {
GeneratedAdapter generatedAdapter = createGeneratedAdapter(
constructors.get(0), object);
return new SingleGeneratedAdapterObserver(generatedAdapter);
}
GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()];
for (int i = 0; i < constructors.size(); i++) {
adapters[i] = createGeneratedAdapter(constructors.get(i), object);
}
return new CompositeGeneratedAdaptersObserver(adapters);
}
return new ReflectiveGenericLifecycleObserver(object);
}
If it directly inherits from DefaultLifecycleObserver, a FullLifecycleObserverAdapter will be generated. In its implementation of the onStateChanged callback method, the final lifecycle state will be dispatched, which leads back to the LifecycleListener1 created initially. Thus, the Activity's lifecycle state is monitored in LifecycleListener1. Let's take a look at the FullLifecycleObserverAdapter source code:
class FullLifecycleObserverAdapter implements GenericLifecycleObserver {
private final FullLifecycleObserver mObserver;
FullLifecycleObserverAdapter(FullLifecycleObserver observer) {
mObserver = observer;
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
// Call the corresponding lifecycle method based on the specific Event
switch (event) {
case ON_CREATE:
mObserver.onCreate(source);
break;
case ON_START:
mObserver.onStart(source);
break;
case ON_RESUME:
mObserver.onResume(source);
break;
case ON_PAUSE:
mObserver.onPause(source);
break;
case ON_STOP:
mObserver.onStop(source);
break;
case ON_DESTROY:
mObserver.onDestroy(source);
break;
case ON_ANY:
throw new IllegalArgumentException("ON_ANY must not be sent by anybody");
}
}
}
Initialization of ProcessLifecycleOwner#
We know that the lifecycle state listening in Activity uses ActivityLifecycleCallbacks, and the registration of ActivityLifecycleCallbacks is done in the Application. So how is it registered? The registration is completed in the initialization of ProcessLifecycleOwner, and the call to the init method of ProcessLifecycleOwner can be found in the onCreate method of ProcessLifecycleOwnerInitializer, as shown in the source code below:
public class ProcessLifecycleOwnerInitializer extends ContentProvider {
@Override
public boolean onCreate() {
LifecycleDispatcher.init(getContext());
// Initialize ProcessLifecycleOwner
ProcessLifecycleOwner.init(getContext());
return true;
}
// ...
}
Evidently, ProcessLifecycleOwnerInitializer is a ContentProvider, and its onCreate method initializes ProcessLifecycleOwner after initializing LifecycleDispatcher. The source code for LifecycleDispatcher is as follows:
class LifecycleDispatcher {
private static AtomicBoolean sInitialized = new AtomicBoolean(false);
// LifecycleDispatcher initialization
static void init(Context context) {
if (sInitialized.getAndSet(true)) {
return;
}
// Register ActivityLifecycleCallbacks
((Application) context.getApplicationContext())
.registerActivityLifecycleCallbacks(new DispatcherActivityCallback());
}
@SuppressWarnings("WeakerAccess")
@VisibleForTesting
static class DispatcherActivityCallback extends EmptyActivityLifecycleCallbacks {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
// Add a non-UI Fragment in the Activity
ReportFragment.injectIfNeededIn(activity);
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
}
private LifecycleDispatcher() {
}
}
Combining the previous analysis, the ActivityLifecycleCallbacks registered here and the ActivityLifecycleCallbacks registered earlier serve completely different purposes. The one here is to add a non-UI Fragment in the Activity, while the one above is to dispatch the Activity's lifecycle state. It can be seen that to ensure the addition of the non-UI Fragment, namely ReportFragment, it is added twice, but the injectIfNeededIn method will only add it a second time if it has not been added yet.
Previously, we learned that ProcessLifecycleOwnerInitializer is a ContentProvider. When the ContentProvider is created, it will also start with the creation of the corresponding process. You can start from the main method of ActivityThread to see the startup process of the ContentProvider. By the way, I recommend a tool for viewing Android source code: AndroidXRef, which can be found on Baidu or Google.