Android源碼分析——Activity的啟動過程

最近在看維術的Android插件化原理解析萄喳,需要補充一些Framework層的知識,首先來研究Activity的啟動過程猾愿。

Activity的啟動從Activity類中startActivity方法(先看Actiivty中的充择,后面再看Context中的,本質是一樣的)開始匪蟀。跟著這個方法一步一步跟蹤,會發(fā)現(xiàn)它最后在startActivityForResult里面調用了Instrument對象的execStartActivity方法宰僧;
Instrumentation類中的execStartActivity方法材彪,源碼如下:

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();
            int result = ActivityManagerNative.getDefault()
                .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) {
        }
        return null;
    }

發(fā)現(xiàn)最終調用的是ActivityManagerNative類中的startActivity方法。ActivityManagerNative指的是Binder本地對象琴儿,這個類是抽象類段化,它的實現(xiàn)是ActivityManagerService;因此對于AMS的最終操作都會進入ActivityManagerService這個真正實現(xiàn)造成,接著調用startActivityAsUser方法显熏,最終調用ActivityStackSupervisor類中的startActivityMayWait方法,ActivityStackSupervisor這個類低版本沒有晒屎,在startActivityMayWait中調用startActivityLocked之后處理的都是Activity任務棧相關內容喘蟆,這一系列ActivityStack和ActivityStackSupervisor糾纏不清的調用看下圖就明白了;


調用流程圖

ActivityStack類中的resumeTopActivityLocked方法中調用ActivityStack中的resumeTopActivityInnerLocked鼓鲁,然后在改方法中調用ActivityStackSupervisor類中的startSpecificActivityLocked方法:

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

        r.task.stack.setLaunchTime(r);
        //如果App已經(jīng)運行了蕴轨,直接創(chuàng)建Activity
        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);
                }
                //真正啟動Activity
                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.
        }
        //如果App還沒有運行,創(chuàng)建ActivityThread的進程骇吭,然后創(chuàng)建Activity
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
        //走到這里會先創(chuàng)建ActivityThread的進程橙弱,在ActivityThread的main方法中調用attach方法,
        //接著調用AMS的attachApplication方法,接著調用AMS的attachApplicationLocked棘脐,
        //接著調用ActivityStackSupervisor的attachApplicationLocked斜筐,
        //接著調用realStartActivityLocked方法創(chuàng)建Activity
    }

接著在改方法中調用realStartActivityLocked,人如其名蛀缝,這個方法開始了真正的“啟動Activity”:它調用了ApplicationThread的scheduleLaunchActivity方法顷链,開始了真正的Activity對象創(chuàng)建以及啟動過程。

ApplicationThread是ActivityThread中定義的內部類内斯,繼承ApplicationThreadNative(ApplicationThreadNative extends Binder implements IApplicationThread )蕴潦,ApplicationThread實際上是一個Binder對象,是App所在的進程與AMS所在進程system_server通信的橋梁俘闯。

這里的scheduleLaunchActivity方法直接把啟動Activity的任務通過一個消息轉發(fā)給了主線程潭苞;我們查看Handler類對于這個消息的處理:

case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;

可以看到,這里直接調用了ActivityThread的handleLaunchActivity方法真朗,在這個方法內部有一句非常重要:

Activity a = performLaunchActivity(r, customIntent);

繞了這么多彎此疹,我們的Activity終于被創(chuàng)建出來了!這個方法做了兩件很重要的事情:
使用ClassLoader加載并通過反射創(chuàng)建Activity對象:

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

如果Application還沒有創(chuàng)建遮婶,那么創(chuàng)建Application對象并回調相應的生命周期方法蝗碎;

Application app = r.packageInfo.makeApplication(false, mInstrumentation);

Activity的啟動過程到這里就結束了,這里調用了一系列方法旗扑,大多數(shù)方法我也不知道是干嘛的蹦骑,留待以后研究,畢竟代碼邏輯還是很復雜的臀防。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末眠菇,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子袱衷,更是在濱河造成了極大的恐慌捎废,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件致燥,死亡現(xiàn)場離奇詭異登疗,居然都是意外死亡,警方通過查閱死者的電腦和手機嫌蚤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門辐益,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人脱吱,你說我怎么就攤上這事荷腊。” “怎么了急凰?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵女仰,是天一觀的道長猜年。 經(jīng)常有香客問我,道長疾忍,這世上最難降的妖魔是什么乔外? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮一罩,結果婚禮上杨幼,老公的妹妹穿的比我還像新娘。我一直安慰自己聂渊,他們只是感情好差购,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著汉嗽,像睡著了一般欲逃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上饼暑,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天稳析,我揣著相機與錄音,去河邊找鬼弓叛。 笑死彰居,一個胖子當著我的面吹牛,可吹牛的內容都是我干的撰筷。 我是一名探鬼主播陈惰,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼毕籽!你這毒婦竟也來了奴潘?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤影钉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后掘剪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體平委,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年夺谁,在試婚紗的時候發(fā)現(xiàn)自己被綠了廉赔。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡匾鸥,死狀恐怖蜡塌,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情勿负,我是刑警寧澤馏艾,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響琅摩,放射性物質發(fā)生泄漏铁孵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一房资、第九天 我趴在偏房一處隱蔽的房頂上張望蜕劝。 院中可真熱鬧,春花似錦轰异、人聲如沸岖沛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽婴削。三九已至,卻和暖如春戳稽,著一層夾襖步出監(jiān)牢的瞬間馆蠕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工惊奇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留互躬,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓颂郎,卻偏偏與公主長得像吼渡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子乓序,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內容