本文解釋了使用者點選應用程式圖示之後,Android系統是如何啟動您的應用程式的。 為了將您的應用程式的啟動介面呈現給使用者,Android系統在背後做了很多繁重的工作。 本文將通過重點介紹其中的一些重要階段以及它們之間的順序來詳細闡述應用程式的啟動過程。
Android應用程式有兩個特點:
- 擁有多個入口:Android應用程式由不同的元件組成,它們也可以呼叫其他應用的元件。這些元件就相當於應用程式的多個入口。因此,它們與具有單一入口的傳統應用程式(如main()方法)並不相同。
- 擁有自己的小世界:每個Android應用程式都執行在一個單獨的程式中,它有自己的Dalvik VM例項並被分配一個唯一的使用者ID。
何時啟動應用程式的程式?
在任何需要Android應用程式程式的時候啟動。
每當使用者或其他系統元件請求執行屬於您的應用程式的元件(可能是service,activity或intent receiver)時,Android系統都會為您的應用程式啟動一個新的程式(如果它尚未執行)。一般來說,這個程式會一直執行直到它被系統殺死。 應用程式的程式是按需建立的,並且在您看到應用程式的啟動介面之前會發生許多事情。
每個應用程式都執行在它自己的程式中:預設情況下,每個Android應用程式都執行在自己的Android程式中,它是一個Linux程式,並且會啟動一個執行緒。 例如,當您單擊電子郵件中的超連結時,網頁會在瀏覽器視窗中開啟。 您的郵件客戶端和瀏覽器是兩個獨立的應用程式,它們執行在兩個單獨的獨立程式中。 click事件會導致Android平臺啟動一個新程式,以便它可以在自己的程式中例項化瀏覽器。這同樣適用於應用程式中的其他任何元件。
Zygote : 孕育新的生命,新的程式
先讓我們快速回顧下Android系統的啟動過程。與大多數基於Linux的系統一樣,首先引導載入程式會載入核心並啟動init程式。然後,init程式產生稱為“守護程式”的低階Linux程式,例如android除錯守護程式,USB守護程式等。這些守護程式通常都是用於處理底層硬體介面的。
接下來init程式會啟動一個非常有趣的程式,稱為'Zygote'。
顧名思義,這是Android應用程式的起點。zygote程式在內部會先初始化一個Dalvik虛擬機器的例項,繼而載入所有Android應用程式框架和安裝在系統上的各種應用程式所使用的常用類,最後進入一種監聽狀態,隨時準備被複制。當系統其它模組希望建立新程式時,它們會向zygote程式發出請求,zygote程式監聽到該請求後,會相應地fork出新的程式,於是這個新程式在初生之時,就先天具有了自己的Dalvik虛擬機器以及系統資源。
zygote程式啟動之後,init程式會啟動執行時程式(runtime process)。
然後zygote程式又啟動一個稱為系統服務(system server)的管理良好的程式。 系統服務程式會啟動系統的所有核心服務,比如activity manager service、hardware services。 此時,系統已準備好啟動第一個應用程式 - Home應用程式,該應用程式顯示主螢幕,也稱為應用程式啟動器。
當使用者點選啟動器中的應用程式圖示時...
點選事件被轉換成執行startActivity(intent)方法,並通過Binder IPC路由到ActivityManagerService。ActvityManagerService會執行以下幾個步驟:
- 收集intent的目標Activity的相關資訊。這個過程是通過呼叫PackageManager的resolveIntent()方法完成的。預設使用的是PackageManager.MATCH_DEFAULT_ONLY和PackageManager.GET_SHARED_LIBRARY_FILES引數。
- 目標Activity的相關資訊會被儲存到intent中以避免重新執行此步驟。
- 呼叫grantUriPermissionLocked()方法來檢查使用者是否有足夠的許可權來呼叫intent的目標Activity。
- 如果使用者有足夠的許可權,ActivityManagerService會檢查目標Activity是否需要在新的任務棧中啟動。任務棧的建立依賴於Intent的flag引數,比如FLAG_ACTIVITY_NEW_TASK、FLAG_ACTIVITY_CLEAR_TOP等。
- 最後檢查該應用程式程式的ProcessRecord是否已經存在。如果ProcessRecord為null,ActivityManager會建立一個新的程式來例項化目標Activity。
正如你上面看到的,當使用者點選一個圖示並啟動一個新的應用程式時,背後會發生許多事情。完整的過程如下圖所示:
應用程式程式啟動過程中的三個不同階段:
- Process Creation
- Binding Application
- 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()方法後,便開啟了屬於它的生命週期。