This is the fifth day of my participation in the August Wen Challenge.More challenges in August

Context creation for the Activity

The Activity is created during startup. ActivityThread is the main thread management class for the application process. ScheduleTransaction is eventually called through the ActivityThread inner class ApplicationThread. The scheduleTransaction method of ActivityThread is called internally. The ActivityThread scheduleTransaction method is the ActivityThread’s parent class ClientTransactionHandler. So instead of calling ClientTransactionHandler’s scheduleTransaction method, SendMessage (ActivityThread.h.execute_TRANSACTION, transaction) Is an abstract method implemented by ActivityThread. Therefore, sendMessage calls the sendMessage of the ActivityThread. After the sendMessage of the ActivityThread is called, sendMessage of the mH object of type Hanlder is called. The message what value is the activityThread.h.execute_TRANSACTION passed down from above, Hanlder type mH object is received. What value is ActivityThread H.E XECUTE_TRANSACTION, invoked mTransactionExecutor. Execute (transaction), Execute internal in mTransactionExecutor., calls incoming parameters transaction excute method, finally carry out the task.

As we know from the Activity startup process, the Transaction object is actually of type LaunchActivityItem, so the Excute method for the LaunchActivityItem is called.

public class LaunchActivityItem extends ClientTransactionItem {
    @Override
    public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        / / 1
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mIsForward,
                mProfilerInfo, client, mAssistToken, mFixedRotationAdjustments);
        / / 2
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); }}Copy the code

In the Excute method of the LaunchActivityItem, in comment 1, the ActivityClientRecord object is created. The client’s handleLaunchActivity method is called in comment 2 on an object of type ClientTransactionHandler, as analyzed above, The ActivityThread class inherits ClientTransactionHandler, whose handleLaunchActivity method is abstract, So we need to look at the implementation of the handleLaunchActivity method in ActivityThread.

public final class ActivityThread extends ClientTransactionHandler {

    /** * Extended implementation of activity launch. Used when server requests a launch or relaunch. */
    @Override
    public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent) {...finalActivity a = performLaunchActivity(r, customIntent); .returna; }}Copy the code

The performLaunchActivity method is called in the ActivityThread handleLaunchActivity method

public final class ActivityThread extends ClientTransactionHandler {

    
    /** Core implementation of activity launch. */
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        / / 1
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            / / 2
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if(r.state ! =null) { r.state.setClassLoader(cl); }}catch (Exception e) {
            if(! mInstrumentation.onException(activity, e)) {throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ":"+ e.toString(), e); }}try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if(activity ! =null) {
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if(r.overrideConfig ! =null) {
                    config.updateFrom(r.overrideConfig);
                }
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                Window window = null;
                if(r.mPendingRemoveWindow ! =null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                }

                // Activity resources must be initialized with the same loaders as the
                // application context.
                appContext.getResources().addLoaders(
                        app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
                / / 3
                appContext.setOuterContext(activity);
                / / 4
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken);

                if(customIntent ! =null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if(theme ! =0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                if (r.isPersistable()) {
                    / / 5
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if(! activity.mCalled) {throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                mLastReportedWindowingMode.put(activity.getActivityToken(),
                        config.windowConfiguration.getWindowingMode());
            }
            r.setState(ON_CREATE);

            // updatePendingActivityConfiguration() reads from mActivities to update
            // ActivityClientRecord which runs in a different thread. Protect modifications to
            // mActivities to avoid race.
            synchronized(mResourcesManager) { mActivities.put(r.token, r); }}catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            if(! mInstrumentation.onException(activity, e)) {throw new RuntimeException(
                    "Unable to start activity " + component
                    + ":"+ e.toString(), e); }}returnactivity; }}Copy the code

Create the Activity instance in 2 place, in the note 1 through ContextImpl createBaseContextForActivity method to create the Activity, And pass the ContextImpl into the Attach method of the Activity in comment 4. The setOuterContext method is called in comment 3, assigning the previously created instance of the Activity to the ContextImpl member variable mOuterContext, This also gives ContextImpl access to Activity variables and methods. The onCreate method of the Activity is called in the callActivityOnCreate method of the mInstrumentation in comment 5.

Look at the setOuterContext method in comment 3

public final class ActivityThread extends ClientTransactionHandler {

    private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {... ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig); .returnappContext; }}Copy the code

The createActivityContext method of ContextImpl is called to create the ContextImpl. Look again at the attach method of the activity called in comment 4

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2.Window.Callback.KeyEvent.Callback.OnCreateContextMenuListener.ComponentCallbacks2.Window.OnWindowDismissedCallback.AutofillManager.AutofillClient.ContentCaptureManager.ContentCaptureClient {
    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) { attachBaseContext(context); . }Copy the code

The Attach method of the activity internally calls the attachBaseContext method and the attachBaseContext method of the ContextThemeWrapper

public class ContextThemeWrapper extends ContextWrapper {
    @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(newBase); }}Copy the code

The attachBaseContext method of ContextThemeWrapper’s parent, ContextWrapper, is then called

public class ContextWrapper extends Context {
    Context mBase;
    protected void attachBaseContext(Context base) {
        if(mBase ! =null) {
            throw new IllegalStateException("Base context already set");
        }
        / / 1mBase = base; }}Copy the code

The base at comment 1 is the ContextImpl object passed along, assigned to the ContextWrapper member variable mBase.

To summarize, ContextImpl is created during the creation of the Activity and assigned to the ContextWrapper member variable mBase. The Activity inherits from ContextWrapper’s subclass ContextThemeWrapper, so that methods defined in the Context can be used in the Activity.