Activity的啟動(dòng)原理

前言

? 我還記得上個(gè)學(xué)期意外看到一篇文章,是凱子哥的一篇博客,講的是app第一個(gè)activity啟動(dòng)的底層過(guò)程(java),我當(dāng)時(shí)幾乎沒(méi)接觸過(guò)這塊的源碼,好像看了一半就放棄。還有一次刷知乎,看到一個(gè)人回答為什么ActivityThread里面Loop不會(huì)造成ANR,但是也是一臉萌比。這個(gè)學(xué)期開(kāi)始刷藝術(shù)探索,已經(jīng)看完了第十章,每一章都對(duì)著源碼自己又看了一遍,再加上之前對(duì)Binder,IPC的淺顯的研究。今天重新再來(lái)看這篇文章[【凱子哥帶你學(xué)Framework】Activity啟動(dòng)過(guò)程全解析],發(fā)現(xiàn)基本上是看小說(shuō)一樣的輕松看完了。。這是一種進(jìn)步!!感覺(jué)挺好的。感謝大神的知識(shí)分享,下面我用自己的方式來(lái)總結(jié)一下Activity啟動(dòng)的過(guò)程,但是我跟凱子哥不同,他講的那個(gè)其實(shí)就多了一點(diǎn)Launcher和applicaiton創(chuàng)建的知識(shí)。

? 說(shuō)一點(diǎn)自己的學(xué)習(xí)感受。首先:

  • 源碼海洋里面不要太追求了解每一個(gè)細(xì)節(jié),不然分分鐘迷失自我。
  • 有些知識(shí)是需要有其他知識(shí)儲(chǔ)備才能理解的。所以看不懂的時(shí)候放一放,過(guò)一段時(shí)間再來(lái)看。比如binder設(shè)計(jì)原理那塊我就留了一半。。因?yàn)楹蟀氩糠钟悬c(diǎn)看不太懂了,涉及到了C草。
  • 看書(shū)上的源碼遠(yuǎn)遠(yuǎn)不夠,一定一定要自己去獨(dú)立的看一遍,自己去把整個(gè)流程過(guò)一遍。
  • 畫(huà)草圖,流程圖。因?yàn)檫^(guò)程異常的復(fù)雜,在不同的類(lèi)里面調(diào)來(lái)調(diào)用,又臭又長(zhǎng)的調(diào)用鏈。
  • 永遠(yuǎn)不要放棄,靜下心來(lái)研究,一切都不是問(wèn)題。

知識(shí)儲(chǔ)備

  1. Binder, IPC機(jī)制??梢钥纯次抑暗膬善恼?a target="_blank" rel="nofollow">Android-IPC系列(一)Android-IPC系列(二) 。還有幾篇我覺(jué)得寫(xiě)的非常好的文章Android Binder設(shè)計(jì)與實(shí)現(xiàn) - 設(shè)計(jì)篇 Android進(jìn)程間通信(IPC)機(jī)制Binder簡(jiǎn)要介紹和學(xué)習(xí)計(jì)劃 。(這兩篇講的都比較深)看到藝術(shù)探索后面我終于知道為什么binder要在第二章就講解了。因?yàn)锽inder在后面幾乎是無(wú)處不在!

  2. ActivityManagerService。本質(zhì)就是一個(gè)Binder,并且實(shí)體在服務(wù)端。AMS在遠(yuǎn)端操作著activity的生命周期。這個(gè)進(jìn)程由SystemServer進(jìn)程fork出來(lái)。

  3. ActivityThread。大家都知道ActivityThread就是應(yīng)用的UI線程,main方法就是整個(gè)應(yīng)用的入口。ActivityThread本質(zhì)并不是一個(gè)線程,他只是依附著主線程存在。ActivityThread通過(guò)和AMS進(jìn)行IPC通信來(lái)共同管理Activity的生命周期。在后面我準(zhǔn)備寫(xiě)一篇關(guān)于Handle的續(xù)篇,里面還會(huì)提到他,因?yàn)橹骶€程里面的Looper就是在這里init的。

  4. ApplicationThread.。它是ActivityThread的內(nèi)部類(lèi),本質(zhì)上ActivityThread是通過(guò)它來(lái)進(jìn)行和AMS的IPC通信的。它的本質(zhì)也是一個(gè)Binder!只不過(guò)這次他的實(shí)體放在客戶(hù)端,AMS通過(guò)他的代理類(lèi)ApplicationThreadProxy來(lái)和ApplicationThread通信。

  5. Instrumentation.。這個(gè)類(lèi)我在看完第一遍書(shū)的時(shí)候感覺(jué)操作調(diào)用鏈里面的最外層。因?yàn)樽詈笠徊紸ctivity實(shí)例對(duì)象的生成和onCreat()方法的調(diào)用最終是來(lái)自這個(gè)類(lèi)的。其實(shí)這個(gè)類(lèi)是ActivityThread想要進(jìn)行的操作的具體操作類(lèi)。這個(gè)類(lèi)是全局的,并且每個(gè)acitivity里面都擁有一個(gè)它的引用。

  6. ActivityStack(AMS中)。很好懂,一個(gè)activity棧。但是這個(gè)ActivityStack是有兩種類(lèi)型的,一種叫系統(tǒng)ActivityStack(HomeTask),這一類(lèi)的ActivityStack包含著Launcher(或者有其他我不知道的),還有一種是普通應(yīng)用的ActivityStack(安卓中Task這個(gè)概念的具體實(shí)現(xiàn)形式),其實(shí)就是一個(gè)Task(任務(wù)棧)。這個(gè)類(lèi)是由AMS來(lái)管理,AMS通過(guò)這個(gè)數(shù)據(jù)結(jié)構(gòu)來(lái)得知activity的狀態(tài)。

  7. ActivityStackSuperisor(AMS中)。加了一個(gè)單詞,就是activity棧的管理者。這個(gè)類(lèi)的作用就是管理?xiàng)?,并且通過(guò)ActivityStack來(lái)獲得要啟動(dòng)的activity的信息。

  8. ActivityRecord。這個(gè)就是上面說(shuō)的服務(wù)端的actiivty信息的載體類(lèi)。并且也是服務(wù)端的類(lèi)~這個(gè)類(lèi)相當(dāng)?shù)闹匾?,自始至終都貫穿在調(diào)用鏈里面,在安卓ActivityStack里面存儲(chǔ)的并不是activity實(shí)例,其實(shí)就是這個(gè)ActivityRecord的實(shí)例。

  9. ActivityClientRecord。這個(gè)和上面區(qū)別就是這個(gè)類(lèi)是客戶(hù)端activity信息的載體類(lèi)。

  10. TaskRecord。同樣,這個(gè)類(lèi)就是ActivityTask的信息記錄類(lèi)而已。

    ?好了,我覺(jué)得需要好好了解的幾個(gè)最核心的類(lèi)就是這幾個(gè)了,大家若不清楚,可以自己去源碼里面看,如果我有說(shuō)錯(cuò)的也請(qǐng)?jiān)?。。。其?shí)還有很多概念我在binder那篇文章里面講的不少了!這里算是又一次的補(bǔ)充吧。


Activity啟動(dòng)的流程

? 源碼之旅開(kāi)始??瓶?

1.Activity.startActivity(Intent intent)這個(gè)我們天天都在寫(xiě),好,去看源碼!

@Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

嗯,繼續(xù)看startActivityForResult();

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            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());
            }
            ...省略代碼
    }

直接調(diào)用了Instrumentation去調(diào)用execStartActivity()方法。后面的調(diào)用先不管,直接去看execStartActivity()方法。需要注意的是mMainThread.getApplicationThread()就是通過(guò)ActivityThread去獲得了一個(gè)ApplicaitonThread實(shí)例

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        ...省略代碼
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
          //通過(guò)AMS啟動(dòng)了
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
          //用來(lái)檢測(cè)這個(gè)activity啟動(dòng)的結(jié)果,具體可以去查看源碼
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }

看到這里發(fā)現(xiàn)它又用了個(gè)什么玩意調(diào)用了startActivity()方法,這是什么呢?這里的ActivityManagerNative.getDefault()就是我們期待了很久的ActivityManagerService的代理類(lèi)!如果你很清楚Binder的實(shí)現(xiàn),這個(gè)應(yīng)該難不倒你吧!AMS和代理類(lèi)本質(zhì)上都是IActivityManager的實(shí)現(xiàn)類(lèi)。(IAcitivtyManager,其實(shí)就是一個(gè)AIDL接口,不信自己去看源碼)。我給你看看getDefault()方法的實(shí)現(xiàn):

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

就是這么簡(jiǎn)單!如果看到這里你看不懂了,建議你再回去看看Binder。接下來(lái)我們就可以繼續(xù)看AMS中startActivity()方法的實(shí)現(xiàn)了:注意,從這里開(kāi)始,調(diào)用鏈會(huì)變得很復(fù)雜

@Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) {
      //調(diào)用了startActivityAsUser,caller是我們的ApplicaitonThread
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
    }

繼續(xù)看這個(gè)startActivityAsUser()方法:

@Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.轉(zhuǎn)換app里面的activity棧,caller是我們的ApplicaitonThread
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, userId, null, null);
    }

? 發(fā)現(xiàn)調(diào)用了之前提到的ActivityStackSupervisor的startActivityMayWait()方法。這里的目的就是想去通過(guò)棧的管理者來(lái)通過(guò)傳進(jìn)來(lái)的數(shù)據(jù)去改變棧,并且拿到被啟動(dòng)activity的ActivityRecord實(shí)例。

? 在startActivityMayWait()里面,主要做了ActivityStack, ActivityInfo, LaunchMode等等各種信息的初始化工作,然后就又調(diào)用了startActivityLocked()方法, 這個(gè)方法里面又做了一系列的變量初始化,初始啟動(dòng)的錯(cuò)誤判斷, uid檢查之后,又調(diào)用了startActivityUncheckedLocked()方法。這個(gè)方法里面根據(jù)前面一系列的工作,確定了最終的LanuchMode,這個(gè)LaunchMode會(huì)在后面的函數(shù)被拿來(lái)進(jìn)行判斷,構(gòu)建了一個(gè)新的intent,ActivityInfo,ActivityTask。反正過(guò)程都TM又臭又長(zhǎng),細(xì)看下去一天就耗完了。接下來(lái)我們可以看到最終調(diào)用targetStack.resumeTopActivityLocked()方法。這個(gè)targetStack就是新的activity所要放入的Task的位置。也就是說(shuō),現(xiàn)在又要轉(zhuǎn)到ActivityTask中去看源碼了,科科!

? 注意的是,LaunchMode和ActivityStack的選擇是個(gè)很復(fù)雜的過(guò)程。我推薦一篇文章以及安卓的官方文檔鏈接。官方文檔,頓文的博客


? 需要非常注意的是,這個(gè)函數(shù)執(zhí)行的時(shí)候,被啟動(dòng)的activity里面被添加到棧里面去了,top,next就是指代這個(gè)要被啟動(dòng)的activity。pre,current就是指代當(dāng)前resumed的activity。你別弄混了,雖然這個(gè)問(wèn)題我TM看了一整天的源碼。注意,被啟動(dòng)的activity雖然還沒(méi)有被實(shí)例,但是它的ActivityRecord實(shí)例已經(jīng)被構(gòu)建出來(lái)了,并且已經(jīng)被添加到stack里面去了。具體的調(diào)用過(guò)程是:

? Supervisor.setActivityUnchekedLocked->resumeTopActivityLocked(這里是ActivityStackSuperbisor里面的方法)->ActivityStack.startActivityLocked在這里將activity添加到stack里面。并且在之后才會(huì)調(diào)用ActivityStack的resumeTopActivityLocked方法

/**
     * Ensure that the top activity in the stack is resumed.
     *
     * @param prev The previously resumed activity, for when in the process
     * of pausing; can be null to call from elsewhere.
     *
     * @return Returns true if something is being resumed, or false if
     * nothing happened.
     */
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        if (inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            inResumeTopActivity = true;
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            inResumeTopActivity = false;
        }
        return result;
    }

?

? 不要有情緒,繼續(xù)看resumeTopActivityInnerLocked(prev, options);這個(gè)方法太長(zhǎng)了,我分析了一整天,終于所有體會(huì)吧。這個(gè)方法最終的作用是將啟動(dòng)者activity的生命周期變成paused,這樣之后被啟動(dòng)的activity的實(shí)例創(chuàng)建了之后才能順利的resumed。我們來(lái)看部分代碼:

// Find the first activity that is not finishing.
        //找出棧頂中第一個(gè)沒(méi)有在被finish的activity,既我們要啟動(dòng)的actiivty
        ActivityRecord next = topRunningActivityLocked(null);

        // Remember how we'll process this pause/resume situation, and ensure
        // that the state is reset however we wind up proceeding.
        final boolean userLeaving = mStackSupervisor.mUserLeaving;
        mStackSupervisor.mUserLeaving = false;

        final TaskRecord prevTask = prev != null ? prev.task : null;
        //如果整個(gè)stack里面是空的,那么直接啟動(dòng)launcher
        if (next == null) {
            // There are no more activities!  Let's just start up the
            // Launcher...
            ActivityOptions.abort(options);
            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            // Only resume home if on home display
            final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
                    HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
            //直接resume系統(tǒng)ActivityStack里面的根activity(Launcher)
            return isOnHomeDisplay() &&
                    mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
        }

? 在這里,next這個(gè)變量很關(guān)鍵。它的注釋說(shuō)的是第一個(gè)沒(méi)有正在被銷(xiāo)毀的activity,顯然我們要被啟動(dòng)的activity符合這個(gè)條件。并且如果這個(gè)應(yīng)用級(jí)別的stack是空的,也就是說(shuō)現(xiàn)在應(yīng)該跳轉(zhuǎn)到系統(tǒng)級(jí)別的stack去,也就是顯示系統(tǒng)桌面。

// If the top activity is the resumed one, nothing to do.
        //如果被啟動(dòng)的activity就是當(dāng)前處理Resumed狀態(tài)的activity的話,就什么不做。(一個(gè)activity啟動(dòng)自己就是這種情況)
        if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                    mStackSupervisor.allResumedActivitiesComplete()) {
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            mWindowManager.executeAppTransition();
            mNoAnimActivities.clear();
            ActivityOptions.abort(options);
            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Top activity resumed " + next);
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();

            // Make sure to notify Keyguard as well if it is waiting for an activity to be drawn.
            mStackSupervisor.notifyActivityDrawnForKeyguard();
            return false;
        }

?

? 我注釋說(shuō)的很清楚了,如果要啟動(dòng)的activity已經(jīng)是resumed了,就什么都不做。因?yàn)檫@就是一個(gè)當(dāng)前resumed的activity啟動(dòng)它自己。

// If we are sleeping, and there is no resumed activity, and the top
        // activity is paused, well that is the state we want.
        //如果系統(tǒng)正在休眠,并且當(dāng)前最上層的activity都已經(jīng)是paused狀態(tài)了(top activity就是我們要啟動(dòng)的activity)。那就是完美的狀態(tài)。
        if (mService.isSleepingOrShuttingDown()
                && mLastPausedActivity == next
                && mStackSupervisor.allPausedActivitiesComplete()) {
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            mWindowManager.executeAppTransition();
            mNoAnimActivities.clear();
            ActivityOptions.abort(options);
            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Going to sleep and all paused");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

? 如果系統(tǒng)正在休眠,并且當(dāng)前最上層的activity都已經(jīng)是paused狀態(tài)了(top activity就是我們要啟動(dòng)的activity)。那就是完美的狀態(tài)。

// If we are currently pausing an activity, then don't do anything
        // until that is done.
        if (!mStackSupervisor.allPausedActivitiesComplete()) {
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG,
                                                                     /  "resumeTopActivityLocked: Skip resume: some activity pausing.");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

? 如果我們的app里面正在暫停某個(gè)activity,那么我們什么都不要做等這個(gè)做完,因?yàn)闀和ctivity的過(guò)程是串行的,必須要一個(gè)一個(gè)按順序的來(lái)。不能同時(shí)來(lái),我認(rèn)為原因就是因?yàn)榭蛻?hù)端調(diào)用遠(yuǎn)程服務(wù)的過(guò)程的時(shí)候本地的客戶(hù)端所在線程會(huì)被掛起

/ We need to start pausing the current activity so the top one
        // can be resumed...
        //先把現(xiàn)在的當(dāng)前還是resumed的activity pause了,這樣新加進(jìn)來(lái)的activity才能resume?;A(chǔ)知識(shí)
        boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
        //開(kāi)始暫定現(xiàn)在stack里面所有的activity
        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
        if (mResumedActivity != null) {
            //開(kāi)始pausing當(dāng)前的所有activity,并且返回一個(gè)是否暫定成功的結(jié)果回來(lái)
            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
        }

? 這里就是在做把當(dāng)前啟動(dòng)者activity給pause掉,即至于為什么要這么做。。不用我多說(shuō)了吧。

? startPausingLocked(userLeaving, false, true, dontWaitForPause);這個(gè)函數(shù)跟著看下去就是通過(guò)AMS來(lái)暫停activity的過(guò)程。這個(gè)就不多說(shuō)了,大同小異。

最終在函數(shù)的末尾會(huì)又調(diào)用ActivityStackSupervisor的startSpecificActivityLocked(next, true, true);方法。這個(gè)方法的源碼如下:

void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
      //注意了,這里的app之后會(huì)用到,因?yàn)閍pp.thread就是獲得了applicationthread實(shí)例!
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // Don't add this if it is a platform component that is marked
                    // to run in multiple processes, because this is actually
                    // part of the framework so doesn't make sense to track as a
                    // separate apk in the process.
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
              //將app,信息完整的要啟動(dòng)的ActivityRecord類(lèi)的實(shí)例傳到另一個(gè)方法里面去
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }

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

繼續(xù)跟進(jìn)這個(gè)realStartActivityLocked()(真正啟動(dòng)activity的過(guò)程在這里):

final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {

        r.startFreezingScreenLocked(app, 0);
        if (false) Slog.d(TAG, "realStartActivity: setting app visibility true");
        mWindowManager.setAppVisibility(r.appToken, true);

        // schedule launch ticks to collect information about slow apps.
        r.startLaunchTickingLocked();

        // Have the window manager re-evaluate the orientation of
        // the screen based on the new activity order.  Note that
        // as a result of this, it can call back into the activity
        // manager with a new orientation.  We don't care about that,
        // because the activity is not currently running so we are
        // just restarting it anyway.
        if (checkConfig) {
            Configuration config = mWindowManager.updateOrientationFromAppTokens(
                    mService.mConfiguration,
                    r.mayFreezeScreenLocked(app) ? r.appToken : null);
            mService.updateConfigurationLocked(config, r, false, false);
        }

        r.app = app;
        app.waitingToKill = null;
        r.launchCount++;
        r.lastLaunchTime = SystemClock.uptimeMillis();

        if (localLOGV) Slog.v(TAG, "Launching: " + r);

        int idx = app.activities.indexOf(r);
        if (idx < 0) {
            app.activities.add(r);
        }
        mService.updateLruProcessLocked(app, true, null);
        mService.updateOomAdjLocked();

        final ActivityStack stack = r.task.stack;
        try {
            if (app.thread == null) {
                throw new RemoteException();
            }
            List<ResultInfo> results = null;
            List<Intent> newIntents = null;
            if (andResume) {
                results = r.results;
                newIntents = r.newIntents;
            }

...省略代碼

  //通過(guò)applicaitonthread調(diào)用客戶(hù)端binder實(shí)體的方法。
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState,
                    results, newIntents, !andResume, mService.isNextTransitionForward(),
                    profilerInfo);

      ...省略代碼

        return true;
    }

? 這里面兩個(gè)很重要的參數(shù),一個(gè)是ActivityRecord,一個(gè)是app。前者就是在ActivityStack里面轉(zhuǎn)了一圈之后得出來(lái)的最終要啟動(dòng)的Activity的信息記錄類(lèi)。后者就是用來(lái)獲得ApplicationThread來(lái)通知客戶(hù)端拿這個(gè)ActivityRecord去管理你的activity的生命周期吧!相當(dāng)于AMS給了ActivityThread一個(gè)任務(wù),讓后者去執(zhí)行。同樣,這也是一個(gè)IPC的過(guò)程。最終調(diào)用鏈繞了好大一圈終于又回到了ApplicaitonThread。

? 值得一提的是,凡是schedule開(kāi)頭的函數(shù)都是通過(guò)handler來(lái)做線程調(diào)度的,不服來(lái)辯。我們點(diǎn)進(jìn)去

public final void scheduleResumeActivity(IBinder token, int processState,
                boolean isForward, Bundle resumeArgs) {
            updateProcessState(processState, false);
            sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
        }

? 果然用handler發(fā)送了一個(gè)message。我們來(lái)看handler的處理會(huì)最終調(diào)用handlerLaunchActivity方法:

Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);

? 可以看到activity的實(shí)例是由performLaunchActivity方法生成的。

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

      //獲得一些基本信息
        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);
        }

      //通過(guò)Instrumentation利用類(lèi)加載器來(lái)生成一個(gè)activity實(shí)例
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            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);
            }
        }

      //嘗試生成application
        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);


          //創(chuàng)建contextImpl對(duì)象,并且調(diào)用activity的attach()方法來(lái)進(jìn)行一些activity初始化
            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);

              //設(shè)置activity的theme
                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);
                }
            mActivities.put(r.token, r);


        return activity;
    }

? 做了這些事情

  • 從ActivityClientRecord中獲取獲取組件信息
  • 通過(guò)Instrumentation創(chuàng)建Activity對(duì)象
  • 通過(guò)LoadApk的makeApplication創(chuàng)建application,這個(gè)方法有興趣自己去看,就是一個(gè)單例而已。
  • 創(chuàng)建contextImpl對(duì)象,并且調(diào)用activity的attach()方法來(lái)進(jìn)行一些activity初始化
  • 調(diào)用activity的onCreat()方法

完成整個(gè)過(guò)程調(diào)用 ?。。?!

結(jié)束語(yǔ)

? 系統(tǒng)源碼看起來(lái)確實(shí)感覺(jué)自己置身茫茫大海一樣,特別是要去找一些不理解的問(wèn)題的時(shí)候。比如到底是被啟動(dòng)的activity的ActivityRecord實(shí)例先添加進(jìn)去還是在實(shí)例創(chuàng)建了之后才添加進(jìn)去,這個(gè)問(wèn)題我看源碼著了一天才還沒(méi)有什么結(jié)果,后來(lái)在別人的幫助和查閱老羅的資料才找到問(wèn)題所在。挺不錯(cuò)的一次過(guò)程,確實(shí)細(xì)節(jié)不必死扣,但是有些基本問(wèn)題不懂的話還是應(yīng)該去探究一下。

版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容