Activity的显示过程

Activity.java core\java\android\app

Android进程启动的时候,会调用attach 将自己的 ApplicationThread 对象传到 AMS中,AMS 通过这个ApplicationThread对象和 app 通信。如果有要启动的Activity,那么AMS就会基于ApplicationThread 创建一个clientTransaction的通信对象,(clientTransaction 继承自 Parcel,保证了可以用于进程间传输)
然后呢就在这个通信对象里面封装好两个事件,一个是类型为 LaunchActivityItem 的事件,这个事件会根据里面的参数创造指定的Activity,另一个是 ResumeActivityItem,告知app创造完成后要执行它的onStart 和 onResume 操作,然后发给 app执行。

调用栈是
ActivityStackSupervisor.java ——> realStartActivityLocked

ClientLifecycleManager.java ——> void scheduleTransaction(ClientTransaction transaction)

ClientTransaction.java ——> public void schedule()

ActivityThread.java—> ApplicationThread scheduleTransaction(ClientTransaction transaction)

ClientTransactionHandler.java ——> void scheduleTransaction(ClientTransaction transaction)

ClientTransaction.java ——> public void preExecute(……)

ActivityThread.java—> MSG EXECUTE_TRANSACTION

TransactionExecutor.java ——> public void execute(ClientTransaction transaction)
TransactionExecutor.java ——> executeCallbacks (这里调用的就是LaunchActivityItem)
LaunchActivityItem.java ——>execute() postExecute()

直接看 LaunchActivityItem 吧

LaunchActivityItem.java core\java\android\app\servertransaction

这个类里代码量也不多,我们只看关键代码

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

意思是根据Activity在AMS中的代表 ActivityRecord 这个 对象中的 token 等信息,在app内部创建了一个 ActivityClientRecord 对象,那么一切就能对得上了。

我们打开一个Activity时, 最早是在AMS 中创建一个ActivityRecord,用它来描述Activity在AMS中的状态。创建完成后将这个 ActivityRecord 中的 一个Binder 对象发过来。(发过来的也只是一个Binder代理),app根据这个 Binder对象构建出与之对应的ActivityClientRecord对象。然后根据这个ActivityClientRecord 对象new出真正的Activity。
这样就能搞明白了。

接着看client.handleLaunchActivity,client 就是继承了 ClientTransactionHandler 的ActivityThread。

    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        if (r.profilerInfo != null) {
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }

        if (r.mPendingFixedRotationAdjustments != null) {
            // The rotation adjustments must be applied before handling configuration, so process
            // level display metrics can be adjusted.
            overrideApplicationDisplayAdjustments(r.token, adjustments ->
                    adjustments.setFixedRotationAdjustments(r.mPendingFixedRotationAdjustments));
        }

        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

        // Initialize before creating the activity
        if (!ThreadedRenderer.sRendererDisabled
                && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
            HardwareRenderer.preload();
        }
        WindowManagerGlobal.initialize();

        // Hint the GraphicsEnvironment that an activity is launching on the process.
        GraphicsEnvironment.hintActivityLaunch();

        final Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            if (!r.activity.mFinished && pendingActions != null) {
                pendingActions.setOldState(r.state);
                pendingActions.setRestoreInstanceState(true);
                pendingActions.setCallOnPostCreate(true);
            }
        } else {
            // If there was an error, for any reason, tell the activity manager to stop us.
            try {
                ActivityTaskManager.getService()
                        .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }

        return a;
    }

主要是做一些初始化的操作, 关键点是通过
final Activity a = performLaunchActivity(r, customIntent);
通过 performLaunchActivity 这个方法构建了一个Activity

继续往下,可以发现是通过Instrumentation 这个类反射构建了一个Activity,然后执行它的attach 操作, 做一些初始化。



    /**  Core implementation of activity launch. */
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);//这里使用mInstrumentation 反射创建Activity
            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]));

                appContext.setOuterContext(activity);
                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,//直接调用activity的attach方法,初始化window相关
                        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()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);//这里会调用Activity的OnCreate
                }
                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);
            }
        }

        return activity;
    }

接下来进入正题了

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    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);//把context赋值给mBase,可以通过getBaseContext获取到context

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this, window, activityConfigCallback);//创建一个类型为PhoneWindow的 Window 对象,建立和WMS沟通的桥梁
        mWindow.setWindowControllerCallback(mWindowControllerCallback);//这个回调和android 7.0多任务窗口有关
        mWindow.setCallback(this);//设置callback,各类键盘输出事件的回调
        mWindow.setOnWindowDismissedCallback(this);//设置窗口消失的回调
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);//与输入法有关的设置
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();//设置当前线程为UI线程

        mMainThread = aThread;//保存ActivityThread
        mInstrumentation = instr;//保存mInstrumentation
        mToken = token;//保存ActivityToken  服务端在 ActivityRecord中
        mAssistToken = assistToken;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }

        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);//setWindowManager
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());//为空
        }
        mWindowManager = mWindow.getWindowManager();//保存WM 
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);
        mWindow.setPreferMinimalPostProcessing(
                (info.flags & ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING) != 0);

        setAutofillOptions(application.getAutofillOptions());
        setContentCaptureOptions(application.getContentCaptureOptions());
    }

回到ActivityThread,当activity.attach 调用完成后,会执行
mInstrumentation.callActivityOnCreate(activity, r.state);//这里会调用Activity的OnCreate

callActivityOnCreate 内部就3个函数。最重要的是第二个。

    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);//预处理
        activity.performCreate(icicle);//判断当前Activity 的启动模式,分屏或者是画中画, 调用Activity 的 onCreate,
        postPerformCreate(activity);//
    }


onCreate 之后Activity一般都会执行 setContentView,setContentView 有两个方法,名字相同但是参数不一样,一个是传入id,另一个是传入View 对象,不过本质上是一样的。

    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
}




    public void setContentView(View view) {
        getWindow().setContentView(view);
        initWindowDecorActionBar();
    }

分析代码发现都是调用的getWindow() 的 setContentView 方法。getWindow会返回一个类型为 Window 的 mWindow对象,实际上它是 PhoneWindow。然后调用它的方法setContentView将View 或者是资源ID设置进去

PhoneWindow.java core\java\com\android\internal\policy

我们看第一种,会初始化 DecorView
DecorView是PhoneWindow中的起始节点View,继承于View类,作为整个视图容器来使用。用于设置窗口属性。它本质上是一个FrameLayout
会通过 installDecor, installDecor会调用generateDecor,最终生成一个新的Décor返回

    @Override
    public void setContentView(int layoutResID) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) {//要么是DecorView本身,或者是它的孩子,这里肯定是Null
            installDecor();//初始化 DecorView
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);// 解析我们设置的布局资源并且设置 mContentParent 为父布局
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }




    protected DecorView generateDecor(int featureId) {
        // System process doesn't have application context and in that case we need to directly use
        // the context we have. Otherwise we want the application context, so we don't cling to the
        // activity.
        Context context;
        if (mUseDecorContext) {
            Context applicationContext = getContext().getApplicationContext();
            if (applicationContext == null) {
                context = getContext();
            } else {
                context = new DecorContext(applicationContext, this);
                if (mTheme != -1) {
                    context.setTheme(mTheme);
                }
            }
        } else {
            context = getContext();
        }
        return new DecorView(context, featureId, this, getAttributes());
    }

你可能感兴趣的:(Activity的显示过程)