安卓應(yīng)用啟動詳解:從Zygote到你的Activity.onCreate()

翻譯自:https://android.jlelse.eu/android-application-launch-explained-from-zygote-to-your-activity-oncreate-8a8f036864b

這篇文章講解當用戶點擊應(yīng)用圖標時殖卑,安卓如何啟動你的應(yīng)用醉拓。安卓系統(tǒng)做了很多幕后工作灶体,來使得你的launch activity對用戶可見嫉父。本文通過重要階段的講解和調(diào)用序列詳細講解這一過程盯荤。

安卓應(yīng)用在這兩個方面是獨特的:

多個入口點:Android應(yīng)用程序由不同的組件組成,它們可以調(diào)用其他應(yīng)用程序擁有的組件彪见。這些組件大致對應(yīng)于任何應(yīng)用程序的多個入口點丘薛。因此,它們不同于具有像main()方法那樣的單個入口點的傳統(tǒng)應(yīng)用程序睦柴。
擁有自己的小世界:每個Android應(yīng)用程序都生活在自己的世界中诽凌,它在單獨的進程中運行,擁有自己的Dalvik VM實例坦敌,并分配有唯一的用戶ID侣诵。

Android進程何時開始?

必要時會啟動Android進程狱窘。
每當用戶或其他系統(tǒng)組件請求執(zhí)行屬于您應(yīng)用程序的組件(可能是服務(wù)杜顺,活動或意圖接收器)時,Android系統(tǒng)都會為您的應(yīng)用程序啟動一個新進程(如果尚未運行)蘸炸。通常躬络,進程一直運行直到被系統(tǒng)殺死。應(yīng)用程序流程是按需創(chuàng)建的搭儒,在您看到應(yīng)用程序的啟動活動啟動并運行之前穷当,發(fā)生了許多事情。
每個應(yīng)用程序都在其自己的進程中運行:默認情況下淹禾,每個Android應(yīng)用程序都在其自己的Android進程中運行馁菜,而這個進程只不過是一個Linux進程,而該進程首先需要一個執(zhí)行線程铃岔。例如汪疮,當您單擊電子郵件中的超鏈接時,網(wǎng)頁將在瀏覽器窗口中打開德撬。您的郵件客戶端和瀏覽器是兩個單獨的應(yīng)用程序铲咨,它們分別在兩個單獨的進程中運行。click事件使Android平臺啟動新進程蜓洪,以便它可以在其自身進程的上下文中實例化瀏覽器活動纤勒。這對于應(yīng)用程序中的任何其他組件同樣適用。

Zygote:孕育新生命隆檀,新過程

讓我們退后一會兒摇天,快速瀏覽一下系統(tǒng)啟動過程粹湃。與大多數(shù)基于Linux的系統(tǒng)一樣,啟動加載程序在啟動時將加載內(nèi)核并啟動init進程泉坐。然后为鳄,init會生成稱為“守護程序”的低級Linux進程,例如android debug守護程序腕让,USB守護程序等孤钦。這些守護程序通常處理低級硬件接口,包括無線電接口纯丸。

然后偏形,初始化過程會啟動一個非常有趣的過程,稱為“zygote'觉鼻。

顧名思義俊扭,這是其余Android應(yīng)用程序的開始。這是初始化Dalvik虛擬機的第一個實例的過程坠陈。它還預(yù)加載Android應(yīng)用程序框架和系統(tǒng)上安裝的各種應(yīng)用程序使用的所有常見類萨惑。因此,它準備進行復(fù)制仇矾。它統(tǒng)計偵聽套接字接口上的將來請求庸蔼,以產(chǎn)生新的虛擬機(VM)來管理新的應(yīng)用程序進程。收到新請求后贮匕,它會分叉以創(chuàng)建一個新進程朱嘴,該進程將獲取預(yù)先初始化的VM實例。
zygote之后粗合,init啟動運行時過程萍嬉。
然后zygote分叉以啟動一個名為System server的托管良好的進程。系統(tǒng)服務(wù)器在其自己的上下文中啟動所有核心平臺服務(wù)隙疚,例如活動管理器服務(wù)和硬件服務(wù)壤追。
此時,完整的堆棧已準備就緒供屉,可以啟動第一個應(yīng)用程序流程-主頁應(yīng)用程序行冰,該應(yīng)用程序顯示主屏幕(也稱為啟動器應(yīng)用程序)。

當用戶單擊啟動器中的應(yīng)用程序圖標時…

click事件被轉(zhuǎn)換為startActivity(intent)伶丐,并通過Binder IPC路由到ActivityManagerService悼做。ActvityManagerService執(zhí)行多個步驟

  1. 第一步是收集有關(guān)Intent對象目標的信息。這是通過在PackageManager對象上使用resolveIntent()方法來完成的哗魂。默認情況下肛走,使用PackageManager.MATCH_DEFAULT_ONLYPackageManager.GET_SHARED_LIBRARY_FILES標志。
  2. 目標信息將保存回意圖對象中录别,以避免重新執(zhí)行此步驟朽色。
  3. 下一個重要步驟是檢查用戶是否具有足夠的特權(quán)來調(diào)用意圖的目標組件邻吞。這是通過調(diào)用grantUriPermissionLocked()方法完成的。
  4. 如果用戶具有足夠的權(quán)限葫男,ActivityManagerService會檢查是否需要在新任務(wù)中啟動目標活動抱冷。任務(wù)的創(chuàng)建取決于Intent標志(例如FLAG_ACTIVITY_NEW_TASK)和其他標志(例如FLAG_ACTIVITY_CLEAR_TOP)
  5. 現(xiàn)在梢褐,它的時間來檢查ProcessRecord已經(jīng)存在process.If的ProcessRecord為空旺遮,則ActivityManager有可能創(chuàng)造一個新的進程實例化目標的組成部分。

如您所見盈咳,當用戶單擊圖標并啟動新應(yīng)用程序時趣效,許多事情發(fā)生在幕后。這是全圖:


image.png

流程啟動分為三個不同的階段:

  1. 流程創(chuàng)建
  2. 裝訂申請
  3. 啟動活動/啟動服務(wù)/調(diào)用意圖接收器…

流程創(chuàng)建:

ActivityManagerService通過調(diào)用startProcessLocked()方法創(chuàng)建一個新進程猪贪,該方法通過套接字連接將參數(shù)發(fā)送到Zygote進程。Zygote派生自己并調(diào)用ZygoteInit.main()讯私,然后實例化ActivityThread對象并返回新創(chuàng)建的進程的進程ID热押。

默認情況下,每個進程都有一個線程斤寇。主線程有一個Looper實例來處理來自消息隊列的消息桶癣,并且它在run()方法的每次迭代中都調(diào)用Looper.loop()Looper的工作是從消息隊列中彈出消息并調(diào)用相應(yīng)的方法來處理它們娘锁。然后牙寞,ActivityThread通過隨后調(diào)用Looper.prepareLoop()Looper.loop()來啟動消息循環(huán)。

以下序列詳細捕獲了調(diào)用序列:

<figcaption class="jv jw di dg dh jx jy bo b fc cp ga" data-selectable-paragraph="" style="box-sizing: inherit; font-weight: 400; font-family: sohne, "Helvetica Neue", Helvetica, Arial, sans-serif; line-height: 20px; margin-left: auto; margin-right: auto; max-width: 728px; font-size: 14px; color: rgb(117, 117, 117); margin-top: 10px; text-align: center;">Android應(yīng)用啟動:單擊事件以執(zhí)行Looper調(diào)用順序</figcaption>

應(yīng)用程序綁定:

下一步是將此新創(chuàng)建的過程附加到特定應(yīng)用程序莫秆。這是通過在線程對象上調(diào)用bindApplication()來完成的间雀。此方法將BIND_APPLICATION消息發(fā)送到消息隊列。該消息由Handler對象檢索镊屎,該對象隨后調(diào)用handleMessage()方法以觸發(fā)特定于消息的操作-handleBindApplication()惹挟。此方法調(diào)用makeApplication()方法,該方法將應(yīng)用程序特定的類加載到內(nèi)存中缝驳。

下圖描述了該調(diào)用序列连锯。

<figcaption class="jv jw di dg dh jx jy bo b fc cp ga" data-selectable-paragraph="" style="box-sizing: inherit; font-weight: 400; font-family: sohne, "Helvetica Neue", Helvetica, Arial, sans-serif; line-height: 20px; margin-left: auto; margin-right: auto; max-width: 728px; font-size: 14px; color: rgb(117, 117, 117); margin-top: 10px; text-align: center;">Android應(yīng)用啟動:BIND_APPLICATION消息處理</figcaption>

啟動活動:

在上一步之后,系統(tǒng)包含負責應(yīng)用程序的進程用狱,并將應(yīng)用程序類加載到進程的私有內(nèi)存中运怖。在新創(chuàng)建的流程和現(xiàn)有流程之間,啟動活動的調(diào)用順序很常見夏伊。

實際的啟動過程從realStartActivity()方法開始摇展,方法在應(yīng)用程序線程對象上調(diào)用sheduleLaunchActivity()。此方法將LAUNCH_ACTIVITY消息發(fā)送到消息隊列溺忧。該消息由handleLaunchActivity()方法處理吗购,如下所示医男。

假設(shè)用戶單擊“視頻瀏覽器”應(yīng)用程序。啟動該活動的調(diào)用順序如圖所示捻勉。

<figcaption class="jv jw di dg dh jx jy bo b fc cp ga" data-selectable-paragraph="" style="box-sizing: inherit; font-weight: 400; font-family: sohne, "Helvetica Neue", Helvetica, Arial, sans-serif; line-height: 20px; margin-left: auto; margin-right: auto; max-width: 728px; font-size: 14px; color: rgb(117, 117, 117); margin-top: 10px; text-align: center;">Android應(yīng)用啟動:LAUNCH_ACTIVITY消息處理</figcaption>

該活動通過onCreate()方法調(diào)用開始其托管生命周期镀梭。該活動通過onRestart()調(diào)用進入前臺,并通過onStart()調(diào)用開始與用戶進行交互踱启。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末报账,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子埠偿,更是在濱河造成了極大的恐慌透罢,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冠蒋,死亡現(xiàn)場離奇詭異羽圃,居然都是意外死亡,警方通過查閱死者的電腦和手機抖剿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門朽寞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人斩郎,你說我怎么就攤上這事脑融。” “怎么了缩宜?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵肘迎,是天一觀的道長。 經(jīng)常有香客問我锻煌,道長妓布,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上工猜,老公的妹妹穿的比我還像新娘。我一直安慰自己肛著,他們只是感情好,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布跺讯。 她就那樣靜靜地躺著枢贿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪刀脏。 梳的紋絲不亂的頭發(fā)上局荚,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機與錄音,去河邊找鬼耀态。 笑死轮傍,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的首装。 我是一名探鬼主播创夜,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼仙逻!你這毒婦竟也來了驰吓?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤系奉,失蹤者是張志新(化名)和其女友劉穎檬贰,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缺亮,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡翁涤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了萌踱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片葵礼。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖虫蝶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情倦西,我是刑警寧澤能真,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站扰柠,受9級特大地震影響粉铐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜卤档,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一蝙泼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧劝枣,春花似錦汤踏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至稳诚,卻和暖如春哗脖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工才避, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留橱夭,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓桑逝,卻偏偏與公主長得像棘劣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子肢娘,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

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