我們平時在手機桌面上點擊一個app 圖標馒索, 就能啟動一個app應用姻灶。從用戶角度來看啸胧,這個過程看起來很簡單赶站,但是它的背后又隱藏著什么玄機 ? 在做安卓開發(fā)這么多年后纺念,我覺得有必要認真的分析一下贝椿,啟動一個app 都走了什么流程 。
1. android app 進程基礎理論
1.1 每個Android App都在一個獨立空間里, 意味著其運行在一個單獨的進程中, 擁有自己的VM, 被系統(tǒng)分配一個唯一的user ID陷谱。
1.2 Android App由很多不同組件組成, 這些組件還可以啟動其他App的組件. 因此, Android App并沒有一個類似程序入口的main()方法烙博。
Android進程與Linux進程一樣. 默認情況下, 每個apk運行在自己的Linux進程中. 另外, 默認一個進程里面只有一個線程---主線程. 這個主線程中有一個Looper實例, 通過調用Looper.loop()從Message隊列里面取出Message來做相應的處理.
那么, 這個進程何時啟動的呢?
簡單的說, 進程在其需要的時候被啟動. 任意時候, 當用戶或者其他組件調取你的apk中的任意組件時, 如果你的apk沒有運行, 系統(tǒng)會為其創(chuàng)建一個新的進程并啟動. 通常, 這個進程會持續(xù)運行直到被系統(tǒng)殺死。
關鍵是: 進程是在被需要的時候才創(chuàng)建的烟逊。
2. 啟動流程
關于Android的應用進程在android guide中有這樣的一段描述:
By default, every application runs in its own Linux process. Android starts the process when any of the application’s components need to be executed, then shuts down the process when it’s no longer needed or when the system must recover memory for other applications.
每一個android應用默認都是在他自己的linux進程中運行渣窜。android操作系統(tǒng)會在這個android應用中的組件需要被執(zhí)行的時候啟動這個應用進程,并且會在這個應用進程沒有任何組件執(zhí)行或者是系統(tǒng)需要為其他應用申請更多內存的時候殺死這個應用進程宪躯。所以當我們需要啟動這個應用的四大組件之一的時候如果這個應用的進程還沒有啟動乔宿,那么就會先啟動這個應用程序進程。
用戶點擊Home上的一個App圖標, 啟動一個應用時:
Click事件會調用startActivity(Intent), 會通過Binder IPC機制, 最終調用到ActivityManagerService. 該Service會執(zhí)行如下操作:
- 第一步通過PackageManager的resolveIntent()收集這個intent對象的指向信息.
指向信息被存儲在一個intent對象中. - 下面重要的一步是通過grantUriPermissionLocked()方法來驗證用戶是否有足夠的權限去調用該intent對象指向的Activity.
- 如果有權限, ActivityManagerService會檢查并在新的task中啟動目標activity.
現(xiàn)在, 是時候檢查這個進程的ProcessRecord是否存在了.
如果ProcessRecord是null, ActivityManagerService會創(chuàng)建新的進程來實例化目標activity.
2.1 創(chuàng)建進程
ActivityManagerService調用startProcessLocked()方法來創(chuàng)建新的進程, 該方法會通過前面講到的socket通道傳遞參數(shù)給Zygote進程. Zygote孵化自身, 并調用ZygoteInit.main()方法來實例化ActivityThread對象并最終返回新進程的pid.
ActivityThread隨后依次調用Looper.prepareLoop()和Looper.loop()來開啟消息循環(huán).
流程圖如下:
2.2 綁定Application
接下來要做的就是將進程和指定的Application綁定起來. 這個是通過上節(jié)的ActivityThread對象中調用bindApplication()方法完成的. 該方法發(fā)送一個BIND_APPLICATION的消息到消息隊列中, 最終通過handleBindApplication()方法處理該消息. 然后調用makeApplication()方法來加載App的classes到內存中.
流程如下:
2.3 啟動Activity
經(jīng)過前兩個步驟之后, 系統(tǒng)已經(jīng)擁有了該application的進程. 后面的調用順序就是普通的從一個已經(jīng)存在的進程中啟動一個新進程的activity了.
實際調用方法是realStartActivity(), 它會調用application線程對象中的sheduleLaunchActivity()發(fā)送一個LAUNCH_ACTIVITY消息到消息隊列中, 通過 handleLaunchActivity()來處理該消息.
假設點擊的是一個視頻瀏覽的App, 其流程如下:
在其他博客上看到對于啟動流程的總結访雪,感覺比較通俗易懂
大家都知道 Android是基于Linux系統(tǒng)的详瑞,而在Linux中掂林,所有的進程都是由init進程直接或者是間接fork出來的,當我開機的時候init進程就會fork出一個Android的第一個新的進程Zygote,中文翻譯過來要”受精卵”坝橡,一個很有意識的名字泻帮。為什么這么說呢,當我們Zygote進程跑起來后驳庭,Android為了實現(xiàn)實現(xiàn)資源共用和更快的啟動速度刑顺,通過Zygote進程直接去fork出一些子進程,這就是為什么要”受精卵”的原因饲常,也就是我們的app全部都是基于Zygote上的 ,沒有Zygote就沒有我們狼讨,當Zygote初始化完成之后贝淤,首先會fork它的第一個子進程SystemServer,這個類非常的重要,為什么這么說呢政供?因為系統(tǒng)里面重要的服務都是在這個進程里面開啟的播聪,比如ActivityManagerService、PackageManagerService布隔、WindowManagerService等等离陶,有木有覺得似曾相識當SystemServer跑起來后,這些重要的服務也會隨之創(chuàng)建,系統(tǒng)初始化完成之后我們就會進到系統(tǒng)桌面->Launcher衅檀,其實Launcher也是一個app招刨,它繼承自Activity,當我們點擊桌面上的app后哀军,系統(tǒng)就會為我們的app創(chuàng)建一個進程沉眶,然后啟動我們App的第一個類ActivityThread其實說到底我們的app就是一個main函數(shù),也就是啟動了ActivityThread.main()。我們重點來看下這個類
參考文檔
1杉适、[譯]Android Application啟動流程分析
2谎倔、Android走進源碼告訴你app是如何被啟動的 :這篇博客結合源碼分析的很透徹,不過大篇幅的源碼看著真是頭疼 猿推。
3片习、Activity啟動過程全解析