Activity的顯示過(guò)程

Activity.java core\java\android\app

Android進(jìn)程啟動(dòng)的時(shí)候属拾,會(huì)調(diào)用attach 將自己的 ApplicationThread 對(duì)象傳到 AMS中钞护,AMS 通過(guò)這個(gè)ApplicationThread對(duì)象和 app 通信。如果有要啟動(dòng)的Activity,那么AMS就會(huì)基于ApplicationThread 創(chuàng)建一個(gè)clientTransaction的通信對(duì)象,(clientTransaction 繼承自 Parcel,保證了可以用于進(jìn)程間傳輸)
然后呢就在這個(gè)通信對(duì)象里面封裝好兩個(gè)事件惩坑,一個(gè)是類(lèi)型為 LaunchActivityItem 的事件,這個(gè)事件會(huì)根據(jù)里面的參數(shù)創(chuàng)造指定的Activity也拜,另一個(gè)是 ResumeActivityItem以舒,告知app創(chuàng)造完成后要執(zhí)行它的onStart 和 onResume 操作,然后發(fā)給 app執(zhí)行慢哈。

調(diào)用棧是
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 (這里調(diào)用的就是LaunchActivityItem)
LaunchActivityItem.java ——>execute() postExecute()

直接看 LaunchActivityItem 吧

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

這個(gè)類(lèi)里代碼量也不多蔓钟,我們只看關(guān)鍵代碼

    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);
    }

意思是根據(jù)Activity在AMS中的代表 ActivityRecord 這個(gè) 對(duì)象中的 token 等信息,在app內(nèi)部創(chuàng)建了一個(gè) ActivityClientRecord 對(duì)象卵贱,那么一切就能對(duì)得上了滥沫。

我們打開(kāi)一個(gè)Activity時(shí), 最早是在AMS 中創(chuàng)建一個(gè)ActivityRecord艰赞,用它來(lái)描述Activity在AMS中的狀態(tài)佣谐。創(chuàng)建完成后將這個(gè) ActivityRecord 中的 一個(gè)Binder 對(duì)象發(fā)過(guò)來(lái)。(發(fā)過(guò)來(lái)的也只是一個(gè)Binder代理)方妖,app根據(jù)這個(gè) Binder對(duì)象構(gòu)建出與之對(duì)應(yīng)的ActivityClientRecord對(duì)象。然后根據(jù)這個(gè)ActivityClientRecord 對(duì)象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;
    }

主要是做一些初始化的操作杯瞻, 關(guān)鍵點(diǎn)是通過(guò)
final Activity a = performLaunchActivity(r, customIntent);
通過(guò) performLaunchActivity 這個(gè)方法構(gòu)建了一個(gè)Activity

繼續(xù)往下镐牺,可以發(fā)現(xiàn)是通過(guò)Instrumentation 這個(gè)類(lèi)反射構(gòu)建了一個(gè)Activity,然后執(zhí)行它的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 反射創(chuàng)建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,//直接調(diào)用activity的attach方法,初始化window相關(guān)
                        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);//這里會(huì)調(diào)用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;
    }

接下來(lái)進(jìn)入正題了

    @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旗唁,可以通過(guò)getBaseContext獲取到context

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

        mWindow = new PhoneWindow(this, window, activityConfigCallback);//創(chuàng)建一個(gè)類(lèi)型為PhoneWindow的 Window 對(duì)象畦浓,建立和WMS溝通的橋梁
        mWindow.setWindowControllerCallback(mWindowControllerCallback);//這個(gè)回調(diào)和android 7.0多任務(wù)窗口有關(guān)
        mWindow.setCallback(this);//設(shè)置callback,各類(lèi)鍵盤(pán)輸出事件的回調(diào)
        mWindow.setOnWindowDismissedCallback(this);//設(shè)置窗口消失的回調(diào)
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);//與輸入法有關(guān)的設(shè)置
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();//設(shè)置當(dāng)前線(xiàn)程為UI線(xiàn)程

        mMainThread = aThread;//保存ActivityThread
        mInstrumentation = instr;//保存mInstrumentation
        mToken = token;//保存ActivityToken  服務(wù)端在 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检疫,當(dāng)activity.attach 調(diào)用完成后讶请,會(huì)執(zhí)行
mInstrumentation.callActivityOnCreate(activity, r.state);//這里會(huì)調(diào)用Activity的OnCreate

callActivityOnCreate 內(nèi)部就3個(gè)函數(shù)。最重要的是第二個(gè)屎媳。

    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);//預(yù)處理
        activity.performCreate(icicle);//判斷當(dāng)前Activity 的啟動(dòng)模式夺溢,分屏或者是畫(huà)中畫(huà), 調(diào)用Activity 的 onCreate,
        postPerformCreate(activity);//
    }


onCreate 之后Activity一般都會(huì)執(zhí)行 setContentView,setContentView 有兩個(gè)方法烛谊,名字相同但是參數(shù)不一樣风响,一個(gè)是傳入id,另一個(gè)是傳入View 對(duì)象丹禀,不過(guò)本質(zhì)上是一樣的状勤。

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




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

分析代碼發(fā)現(xiàn)都是調(diào)用的getWindow() 的 setContentView 方法。getWindow會(huì)返回一個(gè)類(lèi)型為 Window 的 mWindow對(duì)象湃崩,實(shí)際上它是 PhoneWindow荧降。然后調(diào)用它的方法setContentView將View 或者是資源ID設(shè)置進(jìn)去

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

我們看第一種,會(huì)初始化 DecorView
DecorView是PhoneWindow中的起始節(jié)點(diǎn)View攒读,繼承于View類(lèi)朵诫,作為整個(gè)視圖容器來(lái)使用。用于設(shè)置窗口屬性薄扁。它本質(zhì)上是一個(gè)FrameLayout
會(huì)通過(guò) installDecor剪返, installDecor會(huì)調(diào)用generateDecor,最終生成一個(gè)新的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);// 解析我們?cè)O(shè)置的布局資源并且設(shè)置 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());
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市日缨,隨后出現(xiàn)的幾起案子钱反,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件面哥,死亡現(xiàn)場(chǎng)離奇詭異哎壳,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)尚卫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)归榕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人吱涉,你說(shuō)我怎么就攤上這事刹泄。” “怎么了怎爵?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵特石,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我疙咸,道長(zhǎng)县匠,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任撒轮,我火速辦了婚禮乞旦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘题山。我一直安慰自己兰粉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布顶瞳。 她就那樣靜靜地躺著玖姑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪慨菱。 梳的紋絲不亂的頭發(fā)上焰络,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天,我揣著相機(jī)與錄音符喝,去河邊找鬼闪彼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛协饲,可吹牛的內(nèi)容都是我干的畏腕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼茉稠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼描馅!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起而线,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤铭污,失蹤者是張志新(化名)和其女友劉穎恋日,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體况凉,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谚鄙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年各拷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刁绒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烤黍,死狀恐怖知市,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情速蕊,我是刑警寧澤嫂丙,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站规哲,受9級(jí)特大地震影響跟啤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜唉锌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一隅肥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧袄简,春花似錦腥放、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至吕粹,卻和暖如春种柑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背匹耕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工聚请, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人泌神。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓良漱,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親欢际。 傳聞我的和親對(duì)象是個(gè)殘疾皇子母市,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容