讀Android源碼-冷啟動(dòng)時(shí)的ActivityThread

前言:
應(yīng)用冷啟動(dòng)時(shí)需要?jiǎng)?chuàng)建進(jìn)程,開(kāi)啟主線程娄琉,實(shí)例化應(yīng)用所需組件次乓。
讀ActivityThread源碼有助于我們了解這個(gè)過(guò)程中,客戶端做的那些事孽水。

冷啟動(dòng)創(chuàng)建應(yīng)用時(shí)票腰,ActivityThread的主要方法:

  1. main()
    -- 1. 開(kāi)啟消息循環(huán)
    -- 2. 通知ActivityManagerService
    -- 3. 添加GCWatcher
  2. handleBindApplication()
    -- 1. 創(chuàng)建LoadedApk
    -- 2. 創(chuàng)建Instrumentation
    -- 3. 創(chuàng)建Application
    -- 4. 通過(guò)Instrumentation調(diào)用Application的onCreate()方法

main()

main方法是一個(gè)應(yīng)用創(chuàng)建的入口,他主要做了3件事

1. 開(kāi)啟消息循環(huán)

調(diào)用Looper.prepareLoop() Looper.loop()女气,開(kāi)啟主線程的消息循環(huán)杏慰,以便于ApplicationThread調(diào)用ActivityThread中的生命周期方法。

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

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

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    ...
    Looper.loop();
}
2. 通知ActivityManagerService

調(diào)用ActivityThread.attach()方法炼鞠,attach()方法在調(diào)用了attachApplication()將ApplicationThread這個(gè)Binder交給了ActivityManagerService缘滥,意味著ActivityManagerService可以通過(guò)ApplicationThread控制我們的應(yīng)用,建立了服務(wù)器端對(duì)客戶端的通信渠道谒主。

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

SDK26以后朝扼,去除了Native和Proxy,而是直接從ActivityManager(ServiceManager)中獲取ActivityManagerService的Binder對(duì)象進(jìn)行通信

3. 添加GCWatcher

在attach()方法中霎肯,添加了監(jiān)聽(tīng)dialvik內(nèi)存使用情況得監(jiān)聽(tīng)者GcWatcher擎颖,當(dāng)內(nèi)存使用超過(guò)總?cè)萘康?/4凹耙,則打印Log進(jìn)行記錄,并且調(diào)用ActivityManagerService的releaseSomeActivities()進(jìn)行內(nèi)存釋放操作肠仪,以防止內(nèi)存溢出導(dǎo)致應(yīng)用崩潰。

private void attach(boolean system){
    ...
    BinderInternal.addGcWatcher(new Runnable() {
        @Override public void run() {
            if (!mSomeActivitiesChanged) {
                return;
            }
            Runtime runtime = Runtime.getRuntime();
            long dalvikMax = runtime.maxMemory();
            long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
            if (dalvikUsed > ((3*dalvikMax)/4)) {
                if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                        + " total=" + (runtime.totalMemory()/1024)
                        + " used=" + (dalvikUsed/1024));
                mSomeActivitiesChanged = false;
                try {
                    mgr.releaseSomeActivities(mAppThread);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
        }
    });
    ...
}

handleBindApplication()

ActivityManagerService=AMS
handleBindApplication的被調(diào)用時(shí)機(jī)是:

  1. 通過(guò)上面AMS.attachApplication()后备典,AMS獲得了控制應(yīng)用的Binder對(duì)象ApplicationThread异旧。
  2. AMS進(jìn)行了一系列操作后(這里先省略),調(diào)用了ApplicationThread的bindApplication()
  3. bindApplication中通過(guò)消息機(jī)制提佣,sendMessage到ActivityThread吮蛹,調(diào)用了ActivityThread的handleBindApplication()

handleBindApplication是創(chuàng)建用于所需組件的入口,他主要做了4件事:

1. 創(chuàng)建LoadedApk

LoadedApk對(duì)象包含應(yīng)用的所有信息

private void handleBindApplication(AppBindData data){
    ...
    final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                    appContext.getClassLoader(), false, true, false);
    ...
}
2. 創(chuàng)建Instrumentation

Instrumentation是應(yīng)用組件的管家拌屏,組件的生命周期方法都需要通過(guò)它來(lái)調(diào)用潮针,是客戶端與服務(wù)器端通信的最后一步。

private void handleBindApplication(AppBindData data){
    ...
    final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
    try {
        final ClassLoader cl = instrContext.getClassLoader();
        mInstrumentation = (Instrumentation)
            cl.loadClass(data.instrumentationName.getClassName()).newInstance();
    } catch (Exception e) {
        throw new RuntimeException(
            "Unable to instantiate instrumentation "
            + data.instrumentationName + ": " + e.toString(), e);
    }
    ...
}
3. 創(chuàng)建Application

調(diào)用了LoadedApk.makeApplication()進(jìn)行Application的創(chuàng)建

private void handleBindApplication(AppBindData data){
    ...
    app = data.info.makeApplication(data.restrictedBackupMode, null);
    ...
}
  • 先通過(guò)ContextImpl.createAppContext()獲得Application的Context
  • 再通過(guò)Instrumentation.newApplication()倚喂,用ClassLoder創(chuàng)建Applicaition
  • 創(chuàng)建后Applicaition調(diào)用自身的attach(Context)方法每篷,將Context與Applicaition綁定,完成創(chuàng)建
LoadedApk.class
public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
    ...
    Application app = null;
    ...
    ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
    app = mActivityThread.mInstrumentation.newApplication(
            cl, appClass, appContext);
    ...
    return app;
}
4. 通過(guò)Instrumentation調(diào)用Application的onCreate()方法
private void handleBindApplication(AppBindData data){
    ...
    mInstrumentation.callApplicationOnCreate(app);
    ...
}

更新中...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末端圈,一起剝皮案震驚了整個(gè)濱河市焦读,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌舱权,老刑警劉巖矗晃,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異宴倍,居然都是意外死亡张症,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)鸵贬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)俗他,“玉大人,你說(shuō)我怎么就攤上這事阔逼≌蓿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵颜价,是天一觀的道長(zhǎng)涯保。 經(jīng)常有香客問(wèn)我,道長(zhǎng)周伦,這世上最難降的妖魔是什么夕春? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮专挪,結(jié)果婚禮上及志,老公的妹妹穿的比我還像新娘片排。我一直安慰自己,他們只是感情好速侈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布率寡。 她就那樣靜靜地躺著,像睡著了一般倚搬。 火紅的嫁衣襯著肌膚如雪冶共。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天每界,我揣著相機(jī)與錄音捅僵,去河邊找鬼。 笑死眨层,一個(gè)胖子當(dāng)著我的面吹牛庙楚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播趴樱,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼馒闷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了叁征?” 一聲冷哼從身側(cè)響起窜司,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎航揉,沒(méi)想到半個(gè)月后塞祈,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帅涂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年议薪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片媳友。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡斯议,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出醇锚,到底是詐尸還是另有隱情哼御,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布焊唬,位于F島的核電站恋昼,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏赶促。R本人自食惡果不足惜液肌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸥滨。 院中可真熱鬧嗦哆,春花似錦谤祖、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至橘券,卻和暖如春额湘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背约郁。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留但两,地道東北人鬓梅。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像谨湘,于是被迫代替她去往敵國(guó)和親绽快。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

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