論一個APP從啓動到主頁面顯示經歷的過程?

前言 (我的觀點.不喜勿噴)

本部份內容是關於Android進階的一些知識總結,涉及到的知識點比較雜,不過都 是面試中幾乎常問的知識點,也是加分的點。 關於這部份內容,可能須要有一些具體的項目實踐。在面試的過程當中,結合具體自 身實踐經歷,才能更加深刻透徹的描繪出來。java

(年前有不少加我,今天才一一回復,發現不少都失效了,須要的能夠從新加一次)

順手留下GitHub連接,須要獲取相關面試等內容的能夠本身去找
https://github.com/xiangjiana/Android-MS
(VX:mm14525201314)android

1、流程概述

啓動流程:
點擊桌面App圖標,Launcher進程採用Binder IPC向system_server進程發起 startActivity請求;
system_server進程接收到請求後,向zygote進程發送建立進程的請求;
Zygote進程fork出新的子進程,即App進程;
App進程,經過Binder IPC向sytem_server進程發起 attachApplication請求;
system_server進程在收到請求後,進行一系列準備工做後,再經過binder IPC向 App進程發送 scheduleLaunchActivity請求;
App進程的binder線程( ApplicationThread)在收到請求後,經過handler向主線 程發送LAUNCH_ACTIVITY消息;
主線程在收到Message後,經過發射機制建立目標Activity,並回調 Activity.onCreate()等方法。
到此,App便正式啓動,開始進入Activity生命週期,執行完 onCreate/onStart/onResume方法,UI渲染結束後即可以看到App的主界面。

上面的一些列步驟簡單介紹了一個APP啓動到主頁面顯示的過程,可能這些流程中 的一些術語看的有些懵,什麼是Launcher,什麼是zygote,什麼是 applicationThread..... 下面咱們一一介紹。git

2、理論基礎

1.zygote

zygote意爲「受精卵「。Android是基於Linux系統的,而在Linux中,全部的進程都是 由init進程直接或者是間接fork出來的,zygote進程也不例外。github

在Android系統裏面,zygote是一個進程的名字。Android是基於Linux System的, 當你的手機開機的時候,Linux的內核加載完成以後就會啓動一個叫「init「的進程。在 Linux System裏面,全部的進程都是由init進程fork出來的,咱們的zygote進程也不 例外面試

咱們都知道,每個App其實都是瀏覽器

  • 一個單獨的dalvik虛擬機
  • 一個單獨的進程

因此當系統裏面的第一個zygote進程運行以後,在這以後再開啓App,就至關於開 啓一個新的進程。而爲了實現資源共用和更快的啓動速度,Android系統開啓新進 程的方式,是經過fork第一個zygote進程實現的。因此說,除了第一個zygote進 程,其餘應用所在的進程都是zygote的子進程,這下你明白爲何這個進程叫「受精 卵」了吧?由於就像是一個受精卵同樣,它能快速的分裂,而且產生遺傳物質同樣的 細胞!服務器

2.system_server

SystemServer也是一個進程,並且是由zygote進程fork出來的。架構

知道了SystemServer的本質,咱們對它就不算太陌生了,這個進程是Android Framework裏面兩大很是重要的進程之一——另一個進程就是上面的zygote進 程。app

爲何說SystemServer很是重要呢?由於系統裏面重要的服務都是在這個進程裏面 開啓的,好比 ActivityManagerServicePackageManagerServiceWindowManagerService等等。框架

3.ActivityManagerService

ActivityManagerService,簡稱AMS,服務端對象,負責系統中全部Activity的生命 週期。 ActivityManagerService進行初始化的時機很明確,就是在SystemServer進程開啓 的時候,就會初始化ActivityManagerService

下面介紹下Android系統裏面的服務器和客戶端的概 念。

其實服務器客戶端的概念不只僅存在於Web開發中,在Android的框架設計中,使 用的也是這一種模式。服務器端指的就是全部App共用的系統服務,好比咱們這裏 提到的ActivityManagerService,和前面提到的PackageManagerServiceWindowManagerService等等,這些基礎的系統服務是被全部的App公用的,當某 個App想實現某個操做的時候,要告訴這些系統服務,好比你想打開一個App,那 麼咱們知道了包名和MainActivity類名以後就能夠打開

Intent intent = new Intent(Intent.ACTION_MAIN); 
  intent.addCategory(Intent.CATEGORY_LAUNCHER); 
  ComponentName cn = new 
  ComponentName(packageName, className); 
  intent.setComponent(cn); startActivity(intent);

可是,咱們的App經過調用startActivity()並不能直接打開另一個App,這個方法會 經過一系列的調用,最後仍是告訴AMS說:「我要打開這個App,我知道他的住址和 名字,你幫我打開吧!」因此是AMS來通知zygote進程來fork一個新進程,來開啓我 們的目標App的。這就像是瀏覽器想要打開一個超連接同樣,瀏覽器把網頁地址發 送給服務器,而後仍是服務器把須要的資源文件發送給客戶端的。

知道了Android Framework的客戶端服務器架構以後,咱們還須要瞭解一件事情, 那就是咱們的App和AMS(SystemServer進程)還有zygote進程分屬於三個獨立的進 程,他們之間如何通訊呢?

App與AMS經過Binder進行IPC通訊,AMS(SystemServer進程)與zygote經過 Socket進行IPC通訊。後面具體介紹。

那麼AMS有什麼用呢?在前面咱們知道了,若是想打開一個App的話,須要AMS去 通知zygote進程,除此以外,其實全部的Activity的開啓、暫停、關閉都須要AMS 來控制,因此咱們說,AMS負責系統中全部Activity的生命週期。 在Android系統中,任何一個Activity的啓動都是由AMS和應用程序進程(主要是 ActivityThread)相互配合來完成的。AMS服務統一調度系統中全部進程的 Activity啓動,而每一個Activity的啓動過程則由其所屬的進程具體來完成。

4.Launcher

當咱們點擊手機桌面上的圖標的時候,App就由Launcher開始啓動了。可是,你有 沒有思考過Launcher究竟是一個什麼東西? Launcher本質上也是一個應用程序,和咱們的App同樣,也是繼承自Activity packages/apps/Launcher2/src/com/android/launcher2/Launcher.java

public final class Launcher extends Activity 
          implements View.OnClickListener, OnLongClickListener, La uncherModel.Callbacks, View.OnTouchListener {
   }

Launcher實現了點擊、長按等回調接口,來接收用戶的輸入。既然是普通的App, 那麼咱們的開發經驗在這裏就仍然適用,好比,咱們點擊圖標的時候,是怎麼開啓 的應用呢?捕捉圖標點擊事件,而後startActivity()發送對應的Intent請求唄!是的,Launcher也是這麼作的,就是這麼easy!

5.Instrumentation和ActivityThread

每一個Activity都持有Instrumentation對象的一個引用,可是整個進程只會存在一個 Instrumentation對象。 Instrumentation這個類裏面的方法大多數和ApplicationActivity有關,這個類就是完成對ApplicationActivity初始化和生命週期的工具 類。Instrumentation這個類很重要,對Activity生命週期方法的調用根本就離不開 他,他能夠說是一個大管家。

ActivityThread,依賴於UI線程。App和AMS是經過Binder傳遞信息的,那麼 ActivityThread就是專門與AMS的外交工做的。

6.ApplicationThread

前面咱們已經知道了App的啓動以及Activity的顯示都須要AMS的控制,那麼咱們便 須要和服務端的溝通,而這個溝通是雙向的。
客戶端-->服務端

並且因爲繼承了一樣的公共接口類,ActivityManagerProxy提供了與 ActivityManagerService同樣的函數原型,使用戶感受不出Server是運行在本地仍是 遠端,從而能夠更加方便的調用這些重要的系統服務。

服務端-->客戶端
仍是經過Binder通訊,不過是換了另一對,換成了ApplicationThreadApplicationThreadProxy

他們也都實現了相同的接口IApplicationThread

private class ApplicationThread extends ApplicationThreadNative {
  }
  public abstract class ApplicationThreadNative extends Binder i mplements IApplicationThread{
  } 
  class ApplicationThreadProxy implements IApplicationThread {
  }

好了,前面羅裏吧嗦的一大堆,介紹了一堆名詞,可能不太清楚,不要緊,下面結 合流程圖介紹。

3、啓動流程

1.建立進程

先從Launcher的 startActivity()方法,經過Binder通訊,調用 ActivityManagerServicestartActivity方法。
一系列折騰,最後調用 startProcessLocked()方法來建立新的進程。
該方法會經過前面講到的socket通道傳遞參數給Zygote進程。Zygote孵化自身。 調用 ZygoteInit.main()方法來實例化 ActivityThread對象並最終返回新進程的pid。
調用 ActivityThread.main()方法, ActivityThread隨後依次調用 Looper.prepareLoop()Looper.loop()來開啓消息循環。

方法調用流程圖以下:

更直白的流程解釋:

①App發起進程:
當從桌面啓動應用,則發起進程即是Launcher所在進程;當從某 App內啓動遠程進程,則發送進程即是該App所在進程。發起進程先經過binder發送 消息給 system_server進程;
②system_server進程:
調用 Process.start()方法,經過socket向zygote進程發送創 建新進程的請求;
③zygote進程:
在執行 ZygoteInit.main()後便進入 runSelectLoop()循環體內,當有 客戶端鏈接時便會執行 ZygoteConnection.runOnce()方法,再通過層層調用後fork 出新的應用進程;
④新進程:
執行 handleChildProc方法,最後調用 ActivityThread.main()方法。

2.綁定Application

上面建立進程後,執行ActivityThread.main()方法,隨後調用attach()方法。

將進程和指定的Application綁定起來。這個是經過上節的ActivityThread對象中調用 bindApplication()方法完成的。該方法發送一個BIND_APPLICATION的消息到消息 隊列中, 最終經過handleBindApplication()方法處理該消息. 而後調用 makeApplication()方法來加載App的classes到內存中。

方法調用流程圖以下:

更直白的流程解釋:

(若是看不懂AMS,ATP等名詞,後面有解釋)

3.顯示Activity界面

通過前兩個步驟以後, 系統已經擁有了該application的進程。 後面的調用順序就是 普通的從一個已經存在的進程中啓動一個新進程的activity了。

實際調用方法是realStartActivity(), 它會調用application線程對象中的 scheduleLaunchActivity()發送一個LAUNCH_ACTIVITY消息到消息隊列中, 經過 handleLaunchActivity()來處理該消息。在 handleLaunchActivity()經過 performLaunchActiivty()方法回調Activity的onCreate()方法和onStart()方法,而後通 過handleResumeActivity()方法,回調Activity的onResume()方法,最終顯示Activity 界面。

更直白的流程解釋:

4、Binder通訊

簡稱:
ATP: ApplicationThreadProxy
AT: ApplicationThread
AMP: ActivityManagerProxy
AMS: ActivityManagerService

圖解:

system_server進程中調用 startProcessLocked方法,該方法最終經過socket方式, 將須要建立新進程的消息告知Zygote進程,並阻塞等待Socket返回新建立進程的pid;
Zygote進程接收到system_server發送過來的消息, 則經過fork的方法,將zygote 自身進程複製生成新的進程,並將 ActivityThread相關的資源加載到新進程app process,這個進程多是用於承載activity等組件;
在新進程app process向 servicemanager查詢system_server進程中binder服務端 AMS, 獲取相對應的Client端,也就是AMP. 有了這一對binder c/s對, 那麼app process即可以經過binder向跨進程system_server發送請求,即 attachApplication()
system_server進程接收到相應binder操做後,通過屢次調用,利用ATP向 app process發送binder請求, 即 bindApplication. system_server擁有ATP/AMS, 每個 新建立的進程都會有一個相應的AT/AMP,從而能夠跨進程 進行相互通訊. 這即是進 程建立過程的完整生態鏈。

以上大概介紹了一個APP從啓動到主頁面顯示經歷的流程,主要從宏觀角度介紹了 其過程,具體可結合源碼理解。

順手留下GitHub連接,須要獲取相關面試等內容的能夠本身去找
https://github.com/xiangjiana/Android-MS
(VX:mm14525201314)

PDF和源碼獲取


感謝支持~

相關文章
相關標籤/搜索