[譯]Android系統是如何啓動應用程序的?從Zygote到Activity的onCreate()

本文解釋了用戶點擊應用程序圖標以後,Android系統是如何啓動您的應用程序的。 爲了將您的應用程序的啓動界面呈現給用戶,Android系統在背後作了不少繁重的工做。 本文將經過重點介紹其中的一些重要階段以及它們之間的順序來詳細闡述應用程序的啓動過程。android

Android應用程序有兩個特色:瀏覽器

  1. 擁有多個入口:Android應用程序由不一樣的組件組成,它們也能夠調用其餘應用的組件。這些組件就至關於應用程序的多個入口。所以,它們與具備單一入口的傳統應用程序(如main()方法)並不相同。
  2. 擁有本身的小世界:每一個Android應用程序都運行在一個單獨的進程中,它有本身的Dalvik VM實例並被分配一個惟一的用戶ID。

什麼時候啓動應用程序的進程?

在任何須要Android應用程序進程的時候啓動。app

每當用戶或其餘系統組件請求執行屬於您的應用程序的組件(多是service,activity或intent receiver)時,Android系統都會爲您的應用程序啓動一個新的進程(若是它還沒有運行)。通常來講,這個進程會一直運行直到它被系統殺死。 應用程序的進程是按需建立的,而且在您看到應用程序的啓動界面以前會發生許多事情。框架

每一個應用程序都運行在它本身的進程中:默認狀況下,每一個Android應用程序都運行在本身的Android進程中,它是一個Linux進程,而且會啓動一個線程。 例如,當您單擊電子郵件中的超連接時,網頁會在瀏覽器窗口中打開。 您的郵件客戶端和瀏覽器是兩個獨立的應用程序,它們運行在兩個單獨的獨立進程中。 click事件會致使Android平臺啓動一個新進程,以便它能夠在本身的進程中實例化瀏覽器。這一樣適用於應用程序中的其餘任何組件。socket

Zygote : 孕育新的生命,新的進程

先讓咱們快速回顧下Android系統的啓動過程。與大多數基於Linux的系統同樣,首先引導加載程序會加載內核並啓動init進程。而後,init進程產生稱爲「守護進程」的低級Linux進程,例如android調試守護進程,USB守護進程等。這些守護進程一般都是用於處理底層硬件接口的。oop

接下來init進程會啓動一個很是有趣的進程,稱爲'Zygote'。線程

顧名思義,這是Android應用程序的起點。zygote進程在內部會先初始化一個Dalvik虛擬機的實例,繼而加載全部Android應用程序框架和安裝在系統上的各類應用程序所使用的經常使用類,最後進入一種監聽狀態,隨時準備被複制。當系統其它模塊但願建立新進程時,它們會向zygote進程發出請求,zygote進程監聽到該請求後,會相應地fork出新的進程,因而這個新進程在初生之時,就先天具備了本身的Dalvik虛擬機以及系統資源。3d

zygote進程啓動以後,init進程會啓動運行時進程(runtime process)。調試

而後zygote進程又啓動一個稱爲系統服務(system server)的管理良好的進程。 系統服務進程會啓動系統的全部核心服務,好比activity manager service、hardware services。 此時,系統已準備好啓動第一個應用程序 - Home應用程序,該應用程序顯示主屏幕,也稱爲應用程序啓動器。cdn

當用戶點擊啓動器中的應用程序圖標時...

點擊事件被轉換成執行startActivity(intent)方法,並經過Binder IPC路由到ActivityManagerService。ActvityManagerService會執行如下幾個步驟:

  1. 收集intent的目標Activity的相關信息。這個過程是經過調用PackageManager的resolveIntent()方法完成的。默認使用的是PackageManager.MATCH_DEFAULT_ONLY和PackageManager.GET_SHARED_LIBRARY_FILES參數。
  2. 目標Activity的相關信息會被保存到intent中以免從新執行此步驟。
  3. 調用grantUriPermissionLocked()方法來檢查用戶是否有足夠的權限來調用intent的目標Activity。
  4. 若是用戶有足夠的權限,ActivityManagerService會檢查目標Activity是否須要在新的任務棧中啓動。任務棧的建立依賴於Intent的flag參數,好比FLAG_ACTIVITY_NEW_TASK、FLAG_ACTIVITY_CLEAR_TOP等。
  5. 最後檢查該應用程序進程的ProcessRecord是否已經存在。若是ProcessRecord爲null,ActivityManager會建立一個新的進程來實例化目標Activity。

正如你上面看到的,當用戶點擊一個圖標並啓動一個新的應用程序時,背後會發生許多事情。完整的過程以下圖所示:

應用程序進程啓動過程當中的三個不一樣階段:

  1. Process Creation
  2. Binding Application
  3. Launching Activity / Starting Service / Invoking intent receiver...

Process Creation

ActivityManagerService經過調用startProcessLocked()方法向Zygote請求建立一個新的進程,該方法經過socket鏈接向Zygote進程發送參數。因而Zygote便複製出一份本身的副本並調用ZygoteInit.main(),而後實例化ActivityThread對象並返回新建立進程的進程ID。

每一個進程都默認有一個線程,即主線程。主線程有一個Looper實例來處理來自消息隊列的消息,在遍歷這個消息隊列的時候,其中的run()方法每次都會調用Looper.loop()。Looper的工做就是從消息隊列中取出消息並調用相應的方法來處理它們。ActivityThread隨後會調用Looper.prepareLoop()和Looper.loop()來啓動消息循環。

下面這個序列圖詳細描述了這一過程:

Application Binding:

下一步是將這個新建立的進程綁定到指定的應用程序上。首先ActivityManagerService調用bindApplication()方法,進而觸發線程對象將BIND_APPLICATION消息發送到消息隊列。Handler檢索此消息,而後調用handleMessage()方法觸發操做handleBindApplication()。該方法會調用makeApplication()方法將應用程序的某些特定的類加載到內存中。

下面這個序列圖詳細描述了這一過程:

Launching an Activity:

在上一步以後,系統已經建立好了應用程序進程,並將應用程序的類加載到了進程的專屬內存中。

Activity的啓動過程從realStartActivity()方法開始,首先ActivityManagerService會調用sheduleLaunchActivity()方法,進而觸發線程對象將LAUNCH_ACTIVITY消息發送到消息隊列。該消息由handleLaunchActivity()方法處理。

假設用戶點擊的是視頻瀏覽器應用程序的圖標,啓動Activity的序列圖以下所示。

Activity調用onCreate()方法後,便開啓了屬於它的生命週期。

相關文章
相關標籤/搜索