This is the sixth article in my AOSP series. The previous contents are as follows:

The Pangu and Nuwa of the Java world — Zygote

The oldest son of the Zygote family, SystemServer

Who woke up Zygote in the Android world?

ActivityManagerService, the ubiquitous system core service, starts process parsing

The paoding ding Activity startup process

All the way from Zygote to SystemServer, from the AMS startup process to the creation of the application process, and then to the last phase of the Activity startup process, today ready to say we are familiar with the Activity life cycle. For the basics of the life cycle, this article on the website explains the life cycle of an Activity in detail. In this article, I’ll look at the lifecycle invocation process from a source perspective.

I’d like to say one more thing about the documentation section of the Android website. This is a great repository for both new knowledge and what you already know. Now EVERY time I review a knowledge point, I will reread the official website documents, and there are always different goods received. My reading notes are also posted at the end of the article.

Back to this article, in fact, if you carefully read the last article paoding Jianniu Activity startup process, it has introduced the call process of the life cycle in detail. It’s just that the reading experience of the previous article is really not very good, so here is the Activity life cycle singled out to say.

Let’s take a look at Google’s classic Activity lifecycle diagram:

I don’t think there’s much to say about this graph, but you know it. But do you understand the transfer process behind each lifecycle?

As we know from the previous article, the Activity is initiated by the application process and is completed by calling AMS with Binder. How does the AMS process callback to the application process life cycle method?

In fact, each lifecycle method in the diagram has the same invocation process, which is very similar. Understand this pattern first, and the other problems will be solved.

Call routines for the lifecycle

To illustrate, consider onCreate(), the life cycle in which the Activity is first called.

Review the Activity startup process, which ends with a call to ActivityStackSupervisor’s realStartActivityLocked() method.

> ActivityStackSupervisor.java

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
                                          boolean andResume, boolean checkConfig) throws RemoteException {...final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                r.appToken);
    // add the LaunchActivityItem callback
    clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                System.identityHashCode(r), r.info,
                mergedConfiguration.getGlobalConfiguration(),
                mergedConfiguration.getOverrideConfiguration(), r.compat,
                r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                profilerInfo));

     final ActivityLifecycleItem lifecycleItem;
     if (andResume) {
         lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
    } else {
        lifecycleItem = PauseActivityItem.obtain();
    }
    // 2. Set the life cycle status
     clientTransaction.setLifecycleStateRequest(lifecycleItem);

    / / 3. Call ClientLifecycleManager. ScheduleTransaction ()mService.getLifecycleManager().scheduleTransaction(clientTransaction); .return true;
}
Copy the code

A lot of extraneous code has been omitted.

The above code builds a ClientTransaction object and calls its addCallback() and setLifecycleStateRequest() methods, respectively, Finally, schchueduleTransaction is mobilized to execute the constructed ClientTransaction object, corresponding to 1, 2, and 3 of the annotation. Let’s look at these three methods.

ClientTransaction.addCallback()

> ClientTransaction.java

    public void addCallback(ClientTransactionItem activityCallback) {
        if (mActivityCallbacks == null) {
            mActivityCallbacks = new ArrayList<>();
        }
        mActivityCallbacks.add(activityCallback);
    }
Copy the code

MActivityCallbacks is a collection of elements of type ClientTransactionItem. AddCallback () passes in LaunchActivityItem, which is the implementation class for ClientTransactionItem.

ClientTransaction.setLifecycleStateRequest()

> ClientTransaction.java

   public void setLifecycleStateRequest(ActivityLifecycleItem stateRequest) {
        mLifecycleStateRequest = stateRequest;
    }
Copy the code

MLifecycleStateRequest represents the final life cycle state that the current ClientTransaction should be in after execution.

ClientLifecycleManager.scheduleTransaction()

Note 3 mService. GetLifecycleManager (.) scheduleTransaction (clientTransaction); , mService getLifecycleManager () returns the ClientLifecycleManager object, is the life cycle of Android 9.0 additional auxiliary processing class, the past is not in the source code. Take a look at its scheduleTransaction() method.

 > ClientLifecycleManager.java

    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient(); // -> ApplicationThread
        transaction.schedule(); // ClientTransaction
        if(! (clientinstanceof Binder)) {
            // If client is not an instance of Binder - it's a remote call and at this point it is
            // safe to recycle the object. All objects used for local calls will be recycled after
            // the transaction is executed on client in ActivityThread.transaction.recycle(); }}Copy the code

The Schedule () method of ClientTransaction is called.

> ClientTransaction.java

    public void schedule(a) throws RemoteException {
        / / call ActivityThread. ApplicationThread. ScheduleTransaction ()
        mClient.scheduleTransaction(this);
    }
Copy the code

To be clear, the method calls so far have been in the process where AMS is, not our application process. So what is mClient? java

private IApplicationThread mClient;
Copy the code

IApplicationThread is a key Binder interface that maintains communication between application processes and AMS. This mClient is the proxy object of the application process in the AMS process, and AMS directs the application process through the mClient.

MClient is just a “puppet” in the process of the AMS, to look for it is ActivityThread ApplicationThread.

private class ApplicationThread extends IApplicationThread.Stub {...@Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            // The scheduleTransaction() method of ClientTransactionHandler is called
            ActivityThread.this.scheduleTransaction(transaction); }... }Copy the code

ActivityThread does not have a scheduleTransaction() method, so the corresponding method of its parent class ClientTransactionHandler is called.

> ClientTransactionHandler.java

    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this); javaThe sendMessage() method is implemented in the ActivityThread class
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
Copy the code

ClientTransactionHandler is an abstract class, and sendMeschusage() is an abstract method implemented in the ActivityThread class, Remember the parameter activityThread.h.execute_TRANSACTION.

> ActivityThread.java

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + "" + mH.codeToString(what)
            + ":" + arg1 + "/"+ obj); java msg.arg1 = arg1; msg.arg2 = arg2;if (async) {
            msg.setAsynchronous(true); chu } mH.sendMessage(msg); }Copy the code

MH, the inner class H of ActivityThread, is a Handler object. We all know that handlers are used to communicate between threads, so which two threads are we talking about here? With the Binder, AMS calls the corresponding methods of the application, executing the application’s Binder thread. The main thread is the one that needs to call back the life cycle, so it is the Binder thread and the main thread that communicate.

class H extends Handler {
        
        public void handleMessage(Message msg) {...case EXECUTE_TRANSACTION:chu
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
                    / / execution TransactionExecutor. The execute ()
                    mTransactionExecutor.execute(transaction);
                    if (isSystem()) {
                        transaction.recycle();
                    }
                    break; . }}Copy the code

After retrieving the ClientTransaction object sent by AMS, call TransactionExecutor’s execute() method to execute the transaction.

> TransactionExecutor.java

    public void execute(ClientTransaction transaction) { clientTransaction.setLifecycleStateRequest(lifecycleItem);
        executeCallbacks(transaction);

        // Execute the lifecycle state
        executeLifecycleState(transaction);

    }
Copy the code

You should get a sense of deja vu when you look at the two methods in execute(). Back to the ActivityStackSupervisor’s realStartActivityLocked() method at the beginning of this article:

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
                                          boolean andResume, boolean checkConfig) throws RemoteException {...// 1. addCallback()
    final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                r.appToken);
    clientTransaction.addCallback(LaunchActivityItem.obtain(new.// 2. setLifecycleStateRequest
         final ActivityLifecycleItem lifecycleItem;
     if (andResume) {
         lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
    } else {
        lifecycleItem = PauseActivityItem.obtain();
    }
     clientTransaction.setLifecycleStateRequest(lifecycleItem);

    / / 3. Call ClientLifecycleManager. ScheduleTransaction ()mService.getLifecycleManager().scheduleTransaction(clientTransaction); .return true;
}
Copy the code

addCallback() >>> executeCallbacks()

setLifecycleStateRequest >>> executeLifecycleState()

ExecuteCallbacks () performs the lifecycle callbacks added by the addCallback() method. The LaunchActivityItem is currently added.

The executeLifecycleState() method synchronizes the current life cycle to the life cycle state set by the setLifecycleStateRequest() method. The current setting is ResumeActivityItem.

Take a look at the source code to see how these two methods are executed.

TransactionExecutor.executeCallbacks()

> TransactionExecutor.java

    public void executeCallbacks(ClientTransaction transaction) {
        finalList<ClientTransactionItem> callbacks = transaction.getCallbacks(); .final int size = callbacks.size();
        for (int i = 0; i < size; ++i) {
            finalClientTransactionItem item = callbacks.get(i); . item.execute(mTransactionHandler, token, mPendingActions); item.postExecute(mTransactionHandler, token, mPendingActions); . }}Copy the code

Get all the callback and loop through the execute() and postExecute() methods. The Calkback here has only one element, LaunchActivityItem.

public class LaunchActivityItem extends ClientTransactionItem {
    @Override
    public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) {
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mIsForward,
                mProfilerInfo, client);
        / / call ActivityThread. HandleLaunchActivity ()
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */); }}Copy the code

The ActivityClientRecord object is built and the handleLaunchActivity() method of the ActivityThread is called.

> ActivityThread.java

    @Override
    public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent) {...// Make sure we are running with the most recent config.
        handleConfigurationChanged(null.null);

        WindowManagerGlobal.initialize();

        finalActivity a = performLaunchActivity(r, customIntent); activityIdleInternalLocked ......return a;
    }
Copy the code

PerformLaunchActivity () was covered in detail in the previous article, and only the lifecycle code remains in the following code.

> ActivityThread.java

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;

        / / get the Context
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;

        java.lang.ClassLoader cl = appContext.getClassLoader();
        // Reflection creates Activity
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);

        The system never terminates an Activity directly to free memory, but rather terminates the process in which the Activity is running. Not only does the system destroy the Activity, it also destroys everything else running in the process.
        if(activity ! =null) {activityIdleInternalLocked

            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embedded  / / get the Context
                    CID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.configCallback);


            int theme = r.activityInfo.getThemeResource();
            if(theme ! =0) {
                // Set the theme
                activity.setTheme(theme);
            }

            activity.mCalled = false;
            / / execution onCreate ()
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            r.activity = activity;
        }
        r.setState(ON_CREATE);

        mActivities.put(r.token, r);


        return activity;
    }
Copy the code

Focus on mInstrumentation. CallActivityOnCreate (). Instrumentation is a very important class, which plays an important role in Activity startup and lifecycle management.

> Instrumentation.java

    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }
Copy the code
> Activity.java

    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        mCanEnterPictureInPicture = true;
        restoreHasCurrentPermissionRequest(icicle);
        // execute onCreate ()
        if(persistentState ! =null) {
            onCreate(icicle, persistentState);
        } else{ onCreate(icicle); }... }Copy the code

The Activity’s onCreate() method is finally executed, and the executeCallbacks() method ends there. Of course, onCreate() is not a permanent state, so how do you transition to the next life cycle? Look at the executeLifecycleState() method.

TransactionExecutor.executeLifecycleState()

> TransactionExecutor.java

    private void executeLifecycleState(ClientTransaction transaction) {
        final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
        if (lifecycleItem == null) {
            // No lifecycle request, return early.
            return; }...// Cycle to the state right before the final requested state.
        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);

        // Execute the final transition with proper parameters.
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }
Copy the code

The executeLifecycleState() method takes the ResumeActivityItem as an argument, and its Execute () method is called directly from within the method.

> ResumeActivityItem.java

    @Override
    public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) {
        client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
                "RESUME_ACTIVITY");
    }
Copy the code

And you can see the onCreate () routines are the same, call ActivityThread. HandleResumeActivity (), followed by Instrumentation. CallActivityOnResume (), Finally, call back activity.onresume ().

Once again a lifecycle is complete, onResume() is a relatively permanent lifecycle state.

TransactionExecutor.cycleToPath()

Wait, do you feel like something’s wrong? Where is onStart()?

The normal lifecycle flow would be onCreate() -> onStart() -> onResume(), but the code doesn’t seem to show the call. The lifecycle synchronization is done in the cycleToPath() method of executeLifecycleState(). If you are in onCreate() state and setLifecycleState() sets the final state to onResume(), you need to execute the state between onCreate and onResume, that is, onStart(). Here is a brief look at the source code.

> TransactionExecutor.java

    private void cycleToPath(ActivityClientRecord r, int finish,
            boolean excludeLastState) {
        final int start = r.getLifecycleState();
        log("Cycle from: " + start + " to: " + finish + " excludeLastState:" + excludeLastState);
        final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
        performLifecycleSequence(r, path);
    }
Copy the code

The getLifecyclePath() method calculates the intermediate lifecycle path based on start and Finish. So this is ON_START.

> TransactionExecutor.java

    private void performLifecycleSequence(ActivityClientRecord r, IntArray path) {
        final int size = path.size();
        for (int i = 0, state; i < size; i++) {
            state = path.get(i);
            log("Transitioning to state: " + state);
            switch (state) {
                case ON_CREATE:
                    mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                            null /* customIntent */);
                    break;
                case ON_START:
                    mTransactionHandler.handleStartActivity(r, mPendingActions);
                    break;
                case ON_RESUME:
                    mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
                            r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
                    break;
                case ON_PAUSE:
                    mTransactionHandler.handlePauseActivity(r.token, false /* finished */.false /* userLeaving */.0 /* configChanges */, mPendingActions,
                            "LIFECYCLER_PAUSE_ACTIVITY"); > TransactionExecutor.java"LIFECYCLER_STOP_ACTIVITY");
                    break;
                case ON_DESTROY:
                    mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */.0 /* configChanges */.false /* getNonConfigInstance */."performLifecycleSequence. cycling to:" + path.get(size - 1));
                    break;
                case ON_RESTART:
                    mTransactionHandler.performRestartActivity(r.token, false /* start */);
                    break;
                default:
                    throw new IllegalArgumentException("Unexpected lifecycle state: "+ state); }}}Copy the code

Find ON_START branch, call the ActivityThread handleStartActivity () method, which is the same routine, there is no longer here.

By analogy, ActivityThread should have the following methods:

handleLaunchActivity()
handleStartActivity()
handleResumeActivity()
handlePauseActivity()
handleStopActivity()
handleDestroyActivity()
Copy the code

OnCreate (), onStart(), onResume(), onPause (), onDestroy(), onStop (), onResume(), onPause (), onDestroy(), onPause (), onStop (), onDestroy(), onStart(), onResume(), onStart(), onResume(), onStart(), onResume()

Share some notes from my reading of the official documentation related to the Activity lifecycle.

onCreate

You must implement this callback, which is triggered when the system first creates the Activity. The Activity enters the created state after it is created. This logic should only happen once in the Activity’s lifetime.

onStart

This callback is called when the Activity enters the “Started” state. The onStart() call makes the Activity visible to the user because the application prepares the Activity to come to the foreground and support interaction.

The onStart() method completes very quickly, and like the “created” state, the Activity is not always in the “Started” state. Once this callback ends, the Activity enters the resumed state and the onResume() method is called.

onResume

The Activity comes to the foreground when it enters the “Resumed” state, and the system calls the onResume() callback. This is the state of the application interacting with the user. The app stays that way until something happens that takes the focus away from the app.

onPause

The system sees this method as the first indication that the user is leaving your Activity (although this does not always mean that the Activity is being destroyed); This method indicates that the Activity is no longer in the foreground (although it is still visible if the user is in multi-window mode).

The onPause() execution is very simple, and there is not necessarily enough time to perform the save operation. Therefore, you should not use onPause() to save application or user data, make network calls, or perform database transactions. Because such work may not be completed until this method is completed.

Completing onPause() does not mean that the Activity leaves the “paused” state. Instead, the Activity remains in this state until it recovers or becomes completely invisible to the user.

onStop

If your Activity is no longer visible to the user, it has entered the stopped state, so the onStop() callback is called.

In the onStop() method, the application should release or adjust unwanted resources that are not visible to the user.

You should also use onStop() to perform CPU intensive shutdown operations.

When the Activity enters the Stopped state, it can either return to interacting with the user or it can end and disappear.

onDestroy

Before destroying the Ativity, onDestroy() is called. The system calls this callback for the following reasons:

  1. The Activity is ending (either because the user closed the Activity completely or because the system called finish() for the Activity).
  2. The system temporarily destroys the Activity due to a configuration change (such as device rotation or multi-window mode)

The system never terminates an Activity directly to free memory, but rather terminates the process in which the Activity is running. Not only does the system destroy the Activity, it also destroys everything else running in the process.

The last

So far, we’ve delved into the Activity launch process, the Activity lifecycle process. But there’s a lot of information about Activity.

What is an Activity? What does an Activity consist of? How is an Activity displayed on the screen?

You can write four or five more articles for Activity, so stay tuned.

– line

Bought a server, set up a Halo blog, and did a good job of organizing the series of articles I had written. Recommend domain name! Recommend domain name! Recommend domain name!

The first wechat official account: Bingxin said TM, focusing on Kotlin, Java, Android original knowledge sharing, AOSP source code analysis.

More latest original articles, scan code to pay attention to me!