Android框架簡(jiǎn)介--Activity--Activity啟動(dòng)

以Activity A 啟動(dòng) Activity B,Activity B所在進(jìn)程未啟動(dòng)為例
大體經(jīng)過(guò)已經(jīng)幾個(gè)階段:

startActivity.png

第一步 Activity A 調(diào)用AMS 啟動(dòng)接口

這是一個(gè)binder通訊勋桶,正常啟動(dòng)Activity的方式脱衙,一般我們都會(huì)通過(guò)以下的方式啟動(dòng)一個(gè)新的Activity

startActivity(new Intent(A_Activity.this,B_Activity.class));

這是Activity類的接口侥猬,最終會(huì)調(diào)用到

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
          
        }
    }

這里關(guān)鍵點(diǎn)會(huì)調(diào)用Instrumentation 的execStartActivity方法。
frameworks/base/core/java/android/app/Instrumentation.java
源碼注釋大體意思是Instrumentation類會(huì)在應(yīng)用的任何代碼執(zhí)行前被實(shí)列化捐韩,用來(lái)監(jiān)控系統(tǒng)與應(yīng)用的交互退唠。可在以應(yīng)用的AndroidManifest.xml中<instrumentation>標(biāo)簽來(lái)注冊(cè)一個(gè)Instrumentation的實(shí)現(xiàn)荤胁。
基本上在application和activity的所有生命周期調(diào)用中瞧预,都會(huì)先調(diào)用instrumentation的相應(yīng)方法。Instrumentation另一個(gè)重要作用是提供Android組件單元測(cè)試仅政。這里不做深究垢油。

 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
       ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            //核心在這一句
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

ActivityManager.getService().startActivity 這一步會(huì)通過(guò)binder的方式調(diào)用到AMS的接口

第二步 收集應(yīng)用信息,pause ActivityA

startActivity --> startActivityAsUser -- > mActivityStarter.startActivityMayWait

這里會(huì)調(diào)用到類 ActivityStarter

/**
 * Controller for interpreting how and then launching activities.
 *
 * This class collects all the logic for determining how an intent and flags should be turned into
 * an activity and associated task and stack.
 */
class ActivityStarter

從注釋上看圆丹,我們了解了ActivityStarter的作用是收集所有的邏輯滩愁,用來(lái)決定如何啟動(dòng)activity, ActivityStarter又通過(guò)ActivityStackSupervisor來(lái)管理ActivityStack

略過(guò)中間環(huán)節(jié)辫封,會(huì)調(diào)用到ActivityStack的resumeTopActivityInnerLocked

boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    // ......
    boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
    if (mResumedActivity != null) {
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Pausing " + mResumedActivity);
        pausing |= startPausingLocked(userLeaving, false, next, false);
    }
    // ......
    if (next.attachedToProcess()) {
        try {
        // ......
            transaction.setLifecycleStateRequest(
                    ResumeActivityItem.obtain(next.app.getReportedProcState(),
                            getDisplay().mDisplayContent.isNextTransitionForward()));
            mService.getLifecycleManager().scheduleTransaction(transaction);
        } catch (Exception e) {
            // ......
            mStackSupervisor.startSpecificActivityLocked(next, true, false);
            return true;
        }
        // ......
    } else {
        // Whoops, need to restart this activity!
        if (!next.hasBeenLaunched) {
            next.hasBeenLaunched = true;
        } else {
            if (SHOW_APP_STARTING_PREVIEW) {
                next.showStartingWindow(null /* prev */, false /* newTask */,
                        false /* taskSwich */);
            }
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
        }
        if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }

    return true;
}

此處先通過(guò)startPausingLocked流程使mResumedActivity pause硝枉。

第三步 通過(guò)Zygote創(chuàng)建應(yīng)用進(jìn)程

下一步則通過(guò) ActivityStackSupervisor 中的startSpecificActivityLocked方法來(lái)執(zhí)行啟動(dòng)ActivityB流程

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);


        if (app != null && app.thread != null) {
            try {
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } 

            // If a dead object exception was thrown -- fall through to
            // restart the application.
        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

這個(gè)函數(shù),先判斷ActivityB所在的進(jìn)程是否啟動(dòng)倦微,如果已經(jīng)啟動(dòng)則執(zhí)行realStartActivityLocked妻味, 如果沒(méi)有則走mService.startProcessLocked流程去啟動(dòng)一個(gè)進(jìn)程. mService為ActivityManagerService

private final void startProcessLocked(ProcessRecord app,) {

       if (entryPoint == null) entryPoint = "android.app.ActivityThread";
       startResult = Process.start(entryPoint,);

       synchronized (mPidsSelfLocked) {
                this.mPidsSelfLocked.put(startResult.pid, app);
                if (isActivityProcess) {
                    Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
                    msg.obj = app;
                    mHandler.sendMessageDelayed(msg, startResult.usingWrapper
                            ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
                }
            }
}

frameworks/base/core/java/android/os/Process.java

    public static final ProcessStartResult start(final String processClass,) {
        return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                    debugFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
    }

frameworks/base/core/java/android/os/Process.java

 public final Process.ProcessStartResult start(final String processClass,) {
        try {
            return startViaZygote(processClass, );
        } 
    }

這里 entryPoint = "android.app.ActivityThread" 為啟動(dòng)的java類, 該變量會(huì)作為參數(shù)給到Process欣福。 Process.start(entryPoint,) 最終會(huì)通過(guò)socket跟Zygote通訊弧可,Zygote 會(huì)去fork一個(gè)進(jìn)程,入口就是entryPoint劣欢。

Zygote啟動(dòng)完進(jìn)程后會(huì)返回一個(gè)pid,這個(gè)pid包含在startResult里面裁良,接著會(huì)將pid和app 放入mPidsSelfLocked凿将, 并發(fā)送一個(gè)延時(shí)消息,如果ActivityThread在一定的TIMEOUT(10s)還沒(méi)向AMS報(bào)告价脾,則該消息會(huì)被執(zhí)行牧抵,AMS會(huì)去清除這個(gè)應(yīng)用的所有信息

第四步 應(yīng)用進(jìn)程啟動(dòng)及跟AMS交互

frameworks/base/core/java/android/app/ActivityThread.java

    public static void main(String[] args) {
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        Looper.loop();
    }
 private void attach(boolean system) {
           final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
}

這里的attach就是向AMS注冊(cè)

下面回到AMS中去執(zhí)行

private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
        //首先根據(jù)pid取出 ProcessRecord
        app = mPidsSelfLocked.get(pid);

        //thread為應(yīng)用端的binder對(duì)象,會(huì)去通知應(yīng)用端做一些Application初始化
         thread.bindApplication(processName,...)
         ...
         //處理被掛起的應(yīng)用組件(activity侨把,service犀变,broadcast),之前應(yīng)用進(jìn)程還沒(méi)被創(chuàng)建
         mStackSupervisor.attachApplicationLocked(app)
         ...
         mServices.attachApplicationLocked()

         sendPendingBroadcastsLocked(app)
         
}
boolean attachApplicationLocked(ProcessRecord app)  {
      final ActivityRecord top = stack.topRunningActivityLocked();
      realStartActivityLocked(activity, app,
}

stack為mFocusStack秋柄, 這一部為取出棧頂?shù)腁ctivity获枝,即我們要啟動(dòng)的activity,雖然之前activity沒(méi)啟動(dòng)骇笔,但ams里面棧的信息在啟動(dòng)進(jìn)程前都已經(jīng)準(zhǔn)備好了省店。

final boolean realStartActivityLocked() {
    app.thread.scheduleLaunchActivity
}

app為ProcessRecord對(duì)象嚣崭,thread為應(yīng)用注冊(cè)到AMS的binder對(duì)象. 這里調(diào)用了應(yīng)用的scheduleLaunchActivity,從名字看表示可以加載activity了

第五步 Activity啟動(dòng)

下面就切回到ActivityThread中去執(zhí)行

public final void scheduleLaunchActivity() {
    ActivityClientRecord r = new ActivityClientRecord();
    sendMessage(H.LAUNCH_ACTIVITY, r);
}

通過(guò)發(fā)送消息給主線程去處理

 public void handleMessage(Message msg) {
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {

                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                } break;

getPackageInfoNoCheck 會(huì)去loadApk加載apk的一些信息懦傍,后面啟動(dòng)activity需要調(diào)用到雹舀,下面會(huì)去執(zhí)行的activity的生命周期

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
            }
}
private Activity performLaunchActivity {
      //創(chuàng)建一個(gè)Activity
      activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
       // 獲取之前創(chuàng)建的Application
       Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        //創(chuàng)建Context, 并將Context賦值給activity
        ContextImpl appContext = createBaseContextForActivity(r);
       activity.attach(appContext, this, ...)

       //調(diào)用到Activity onCreate函數(shù) 
       mInstrumentation.callActivityOnCreate(activity, r.state);
       //調(diào)用到Activity onStart函數(shù) 
       activity.performStart();
}

大體流程可以用下圖表示

activity啟動(dòng).png

參考:
網(wǎng)絡(luò)課程 --剖析Framework面試 沖擊Android高級(jí)職位

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市粗俱,隨后出現(xiàn)的幾起案子说榆,更是在濱河造成了極大的恐慌,老刑警劉巖寸认,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件签财,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡废麻,警方通過(guò)查閱死者的電腦和手機(jī)荠卷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)烛愧,“玉大人油宜,你說(shuō)我怎么就攤上這事×耍” “怎么了慎冤?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)沧卢。 經(jīng)常有香客問(wèn)我蚁堤,道長(zhǎng),這世上最難降的妖魔是什么但狭? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任披诗,我火速辦了婚禮,結(jié)果婚禮上立磁,老公的妹妹穿的比我還像新娘呈队。我一直安慰自己,他們只是感情好唱歧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布宪摧。 她就那樣靜靜地躺著,像睡著了一般颅崩。 火紅的嫁衣襯著肌膚如雪几于。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天沿后,我揣著相機(jī)與錄音沿彭,去河邊找鬼。 笑死尖滚,一個(gè)胖子當(dāng)著我的面吹牛膝蜈,可吹牛的內(nèi)容都是我干的锅移。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼饱搏,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼非剃!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起推沸,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤备绽,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后鬓催,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肺素,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年宇驾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了倍靡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡课舍,死狀恐怖塌西,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情筝尾,我是刑警寧澤捡需,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站筹淫,受9級(jí)特大地震影響站辉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜损姜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一饰剥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧摧阅,春花似錦捐川、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)瘸右。三九已至娇跟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間太颤,已是汗流浹背苞俘。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留龄章,地道東北人吃谣。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓乞封,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親岗憋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肃晚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

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