1. 程式人生 > >[譯]Android Application啟動流程分析

[譯]Android Application啟動流程分析


 
  

譯者注: 原文分成兩個部分, 連結如下: http://multi-core-dump.blogspot.com/2010/04/android-application-launch.html http://multi-core-dump.blogspot.com/2010/04/android-application-launch-part-2.html 本文合二為一, 章節標題由譯者加註.

作者曾經在高通的Android效能組工作, 主要工作是優化Android Application的啟動時間.

1, App基礎理論

要想優化App啟動時間, 第一步就是了解App啟動程序的工作原理. 有幾個基礎理論:

Android Application與其他移動平臺有兩個重大不同點:

  1. 每個Android App都在一個獨立空間裡, 意味著其執行在一個單獨的程序中, 擁有自己的VM, 被系統分配一個唯一的user ID.
  2. Android App由很多不同元件組成, 這些元件還可以啟動其他App的元件. 因此, Android App並沒有一個類似程式入口的main()方法.

Android Application元件包括:

  • Activities: 前臺介面, 直接面向User, 提供UI和操作.
  • Services: 後臺任務.
  • Broadcast Receivers: 廣播接收者.
  • Contexnt Providers: 資料提供者.

Android程序與Linux程序一樣. 預設情況下, 每個apk執行在自己的Linux程序中. 另外, 預設一個程序裡面只有一個執行緒---主執行緒. 這個主執行緒中有一個Looper例項, 通過呼叫Looper.loop()從Message佇列裡面取出Message來做相應的處理.

那麼, 這個程序何時啟動的呢? 簡單的說, 程序在其需要的時候被啟動. 任意時候, 當用戶或者其他元件調取你的apk中的任意元件時, 如果你的apk沒有執行, 系統會為其建立一個新的程序並啟動. 通常, 這個程序會持續執行直到被系統殺死. 關鍵是: 程序是在被需要的時候才建立的.

舉個例子, 如果你點選email中的超連結, 會在瀏覽器裡面開啟一個網頁. Email App和瀏覽器App是兩個不同的App, 執行在不同的程序中. 這次點選事件促使Android系統去建立了一個新的程序來例項化瀏覽器的元件.

首先, 讓我們快速看下Android啟動流程. 與眾多基於Linux核心的系統類似, 啟動系統時, bootloader啟動核心和init程序. init程序分裂出更多名為"daemons(守護程序)"的底層的Linux程序, 諸如android debug deamon, USB deamon等. 這些守護程序處理底層硬體相關的介面.

隨後, init程序會啟動一個非常有意思的程序---"Zygote". 顧名思義, 這是一個Android平臺的非常基礎的程序. 這個程序初始化了第一個VM, 並且預載入了framework和眾多App所需要的通用資源. 然後它開啟一個Socket介面來監聽請求, 根據請求孵化出新的VM來管理新的App程序. 一旦收到新的請求, Zygote會基於自身預先載入的VM來孵化出一個新的VM建立一個新的程序.

啟動Zygote之後, init程序會啟動runtime程序. Zygote會孵化出一個超級管理程序---System Server. SystemServer會啟動所有系統核心服務, 例如Activity Manager Service, 硬體相關的Service等. 到此, 系統準備好啟動它的第一個App程序---Home程序了.

2, 啟動App流程

使用者點選Home上的一個App圖示, 啟動一個應用時:

app launch

Click事件會呼叫startActivity(Intent), 會通過Binder IPC機制, 最終呼叫到ActivityManagerService. 該Service會執行如下操作:

  • 第一步通過PackageManager的resolveIntent()收集這個intent物件的指向資訊.
  • 指向資訊被儲存在一個intent物件中.
  • 下面重要的一步是通過grantUriPermissionLocked()方法來驗證使用者是否有足夠的許可權去呼叫該intent物件指向的Activity.
  • 如果有許可權, ActivityManagerService會檢查並在新的task中啟動目標activity.
  • 現在, 是時候檢查這個程序的ProcessRecord是否存在了.

如果ProcessRecord是null, ActivityManagerService會建立新的程序來例項化目標activity.

2.1 建立程序

ActivityManagerService呼叫startProcessLocked()方法來建立新的程序, 該方法會通過前面講到的socket通道傳遞引數給Zygote程序. Zygote孵化自身, 並呼叫ZygoteInit.main()方法來例項化ActivityThread物件並最終返回新程序的pid.

ActivityThread隨後依次呼叫Looper.prepareLoop()和Looper.loop()來開啟訊息迴圈.

流程圖如下:

process creation

2.2 繫結Application

接下來要做的就是將程序和指定的Application繫結起來. 這個是通過上節的ActivityThread物件中呼叫bindApplication()方法完成的. 該方法傳送一個BIND_APPLICATION的訊息到訊息佇列中, 最終通過handleBindApplication()方法處理該訊息. 然後呼叫makeApplication()方法來載入App的classes到記憶體中.

流程如下:

bind application

2.3 啟動Activity

經過前兩個步驟之後, 系統已經擁有了該application的程序. 後面的呼叫順序就是普通的從一個已經存在的程序中啟動一個新程序的activity了.

實際呼叫方法是realStartActivity(), 它會呼叫application執行緒物件中的sheduleLaunchActivity()傳送一個LAUNCH_ACTIVITY訊息到訊息佇列中, 通過 handleLaunchActivity()來處理該訊息.

假設點選的是一個視訊瀏覽的App, 其流程如下:

start activity 作者:anly_jun 連結:http://www.jianshu.com/p/a5532ecc8377 來源:簡書 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。