四大元件以及 Application和Context的全面理解
本文首發於微信公眾號——世界上有意思的事,搬運轉載請註明出處,否則將追究版權責任。個人微訊號:a1018998632,交流qq群:859640274
一、概述

閱讀須知
- 1.文章中的縮寫指代的意思:CI——>ContextImpl、AT——>ActivityThread、LA——>LoadedApk、CR——>ContentResolver、PM——>PackageManager、SP——>SharedPreferences、APT——>ApplicationThread、AMS——>ActivityManagerService、PR——>ProcessRecord、AR——>ActivityRecord、AS——>ActiveServices、SR——>ServicecRecord。
- 2.文章中的變數 mXXX(yyy),括號中 yyy 表示該變數的型別。
- 3.文章中的方法 xxx(yyy),括號中 yyy 表示方法需要傳入的變數型別。
二、用處
- 1.Context的實現類有很多,但是 CI 是唯一做具體工作的,其他實現都是對 CI 做代理。
- 2.CI 中有一些成員物件,先來看看這些物件的用處:
- 1.mSharedPrefsPaths、sSharedPrefsCache:這兩個物件是用於獲取 SharedPreferences 的,在我前一篇部落格裡面有講到。 全面剖析SharedPreferences 。
- 2.mMainThread(AT):這個物件是一個 App 程序的主執行緒,一個 App 的 Framework 層就是從這裡啟動的。
- 3.mPackageInfo(LA):在 AT 初始化 App 的主執行緒的時候,會將 Apk 載入到記憶體中,Apk 在記憶體中就是以這個物件的形式存在的,該物件可以載入 Apk 的資源和 Dex 檔案。
- 4.mUser(UserHandle):多使用者相關。
- 5.mContentResolver( ApplicationContentResolver):繼承於 CR,主要功能是通過 Uri 來獲取檔案、資料庫、Asset、Res 等資料,還有就是通過 ContentProvider 來獲取其他應用和本機資料。
- 6.mResourcesManager(ResourcesManager):單例,因為一個 Apk 不同機型的適配資源,所以用來載入Resource物件,以保證一個 App 中所有的 CI 使用的都是同一份資源。
- 7.mResources(Resources):獲取 Apk 中 Res 資源的物件。
- 8.mOuterContext(Context):用於指向代理本物件的 Context,例如 Activity、Service 等。
- 9.mTheme(Resources.Theme):主題
- 10.mPackageManager(PM):包管理類,不僅可以獲取我們apk包的資訊,還能獲取本機apk包的資訊。
- 3.CI 中有很多 Api,我將這些 Api 歸了一下類
- 1.獲取成員物件:即獲取上面我列出來的那些物件,這些物件獲取到了之後又有更多 Api 暴露出來,在這裡 CI 相當於做了一個聚合。最常用的就是 getResource() 了。
- 2.獲取成員物件的成員物件:即為了方便,CI 封裝了一些常用的獲取成員物件中的資訊的方法。例如getPackageName(),是通過 PM 來獲取的。
- 3.關於 SP 的操作:我們知道 SP 其實就是 Xml 檔案,所以這裡的操作有:獲取、移動、刪除。
- 4.檔案操作:增刪移檔案、開啟檔案流、獲取 App 私有資料夾地址等等。
- 5.資料庫操作:我們知道 Sqlite 其實是一種檔案型資料庫,所以有:開啟、建立、移動、刪除、獲取資料庫檔案路徑,等操作。
- 6.桌布相關操作:這個不是成員變數提供的,WallpaperManager 是系統 Service 一種,所以是SystemService 提供的。
- 7.啟動Activity:包括一般啟動 Acitivyt、多使用者啟動 Activity、啟動多個 Activity。
- 8.廣播操作:傳送普通廣播、傳送需要許可權的廣播、傳送有序廣播、傳送粘連廣播、傳送有序粘連廣播、多使用者廣播、移除各種廣播、註冊各種廣播、取消註冊各種廣播。
- 9.Service 操作:啟動、停止、重啟、繫結、解綁、獲取系統服務以及多使用者操作。
- 10.許可權操作:檢查本 App 是否有某種許可權、檢查某 App 是否有某種許可權、檢查Uri許可權、授予許可權等等。
- 11.各種情況下建立 CI, 這個比較重要 :
- 1.createSystemContext(AT):在 SystemService 建立的時候為其建立一個 CI
- 2.create App Context(AT,LA):在 App lication/Service建立的時候為其建立一個 CI
- 3.createActivityContext(ActivityThread mainThread,LA, IBinder, int displayId,Configuration):在 Activity 建立的時候為其建立一個 CI。
三、四大元件以及 App lication初始化與Context的關係
在瞭解 Binder 的時候有如下要注意的點

1.Activity初始化
-
1.CI.startActivity():將呼叫交給 Instrumentation ( 負責監控 Activity 和 AMS 的互動,所有 Activity 的本地程序到遠端程序的呼叫轉換都是其來執行 ),
-
2.Instrumentation.execStartActivity():傳入一個 APT 然後通過 Binder 機制將呼叫過程轉移到( 後稱AMS )所AMS 在的系統服務程序,本地主執行緒則繼續執行,不過本地主執行緒後續也沒別的操作了。接下來就是本地的MessageQueue 等待 AMS 服務執行完畢,傳送訊息將 Activity 的啟動重新交給本地主執行緒。
-
3.AMS.startActivity():從這裡開始會呼叫會按順序在 ActivityStarter、ActivityStackSupervisor、ActivityStack 這三個類之間進行呼叫,主要會進行下面這些操作,不按順序:
- 1.對 Intent 的內容進行解析,獲取目標 Activity 的資訊。
- 2.根據傳入的 APT 獲取被呼叫 App 的資訊封裝成 PR。
- 3.將1、2和其他資訊結合,將源 Activity 和目標 Activity 封裝成兩個 AR
- 4.解析 Activity 的啟動模式 和當前的 Activity 棧狀態,判斷是否需要建立棧和 Activity 。( 注意這裡的AR 有著 App 中的 Activity 的全部資訊,可以將其看成系統服務裡面的 Activity 的化身 )
- 5.獲取到 Activity 和 Activity 棧之後,接下來要判斷是否要將當前 Activity 執行 onPause() 以及讓使用Binder 執行目標 Activity 的 onCreate() 和 onResume( 注意這裡 onStart() 會在 Binder 遠端呼叫onCreate() 的時候直接執行 ),這裡 AMS 程序會使用 APT 呼叫 App 程序的 Activity 執行相應的生命週期。
- 6.在 AMS 中前置準備一切就緒之後,會通過 APT 使用 Handler 的形式呼叫到 App 程序的 AT 中。
- 7.最終到了ActivityStackSupervisor.realStartActivityLocked()中會使用 APT 將呼叫交給 App 程序——>AT.scheduleLaunchActivity()——>AT.handleLaunchActivity()
-
4.AT.handleLaunchActivity():將有以下操作
- 1.AT.performLaunchActivity:這個方法有以下操作
- 1.建立物件LA(一個 App 只加載一次)
- 2.建立物件 Activity
- 3.建立物件 App lication(一個 App ,只建立一次)
- 4.**建立物件 CI **:CI.createActivityContext()
- 5.Application、CI都 attach 到 Activity 物件:Activity.attach()
- 6.執行 onCreate():Instrumentation.callActivityOnCreate()——>Activity.performCreate()——>Activity.onCreate()
- 7.執行onStart():AT.performLaunchActivity——>Activity.performStart()——>Instrumentation.callActivityOnStart()——>Activity.onStart()
- 2.AT.handleResumeActivity()
- 1.AT.performResumeActivity()——>Activity.performResume()——>Instrumentation.callActivityOnResume()——>Activity.onResume()
- 2.Activity.makeVisible()——>WindowManager.addView():開始進行View的繪製流程。
- 3. 從上面我們可以總結一下:在 AMS 將呼叫交給 App 程序之後,三個生命週期都是在 App 程序被回撥的,並且在 onResume() 之後View才進行繪製
- 1.AT.performLaunchActivity:這個方法有以下操作
2.Service初始化
- 1.CI.startService()——>CI.startServiceCommon():在這裡傳入一個 APT,類似 Activity 啟動時的第二步,將呼叫過程轉移到 AMS 中,本地主執行緒繼續執行,等待 APT 從 AMS 程序將呼叫轉移到本地主執行緒中。
- 2.AMS.startService():到了 AMS 程序之後,Service 的啟動就會全權交給 AS( 這是 AMS 用來管理 Service 的成員變數 )
- 3.AS.startServiceLocked():這裡做了以下操作
- 1.根據傳入的 APT 獲取被呼叫 App 的資訊封裝成 PR
- 2.解析 Intent 等引數獲取到 Service 的資訊,封裝成 SR( 這個類可以看做是 Service 在系統服務的化身,記錄了 Service 的一切資訊 )
- 3.再進過一系列呼叫:AS.startServiceInnerLocked()——>AS.bringUpServiceLocked()——>AS.realStartServiceLocked() 到這裡才是真正在 App 程序啟動 Service 的流程。
- 4.AS.realStartServiceLocked():這裡會有以下操作:
- 1.SR.APT.scheduleCreateService():這裡會將呼叫轉到 App 程序,但是當前的程序還會繼續執行,這裡就到了 App 執行緒的APT,這個方法裡有以下操作
- 1.通過 Handler 轉到 AT.handleCreateService()
- 2.建立物件 LA(一個 App 只加載一次)
- 3.建立物件 Service
- 4. 建立物件 CI
- 5.建立物件 Application(一個 App 只建立一次)
- 6.Application、CI分別 attach 到 Service 物件
- 7.執行 Service.onCreate() 回撥
- 8.此時 Service 已經啟動了
- 2.AS.sendServiceArgsLocked()——>SR. App.APT.scheduleServiceArgs():這裡就轉到了 App 程序的 APT 中,這裡會有以下操作:
- 1.APT.scheduleServiceArgs()
- 2.AT.handleServiceArgs()
- 3.Service.onStartCommand()
- 4.此時我們需要在 Service 中進行的操作將會執行。
- 1.SR.APT.scheduleCreateService():這裡會將呼叫轉到 App 程序,但是當前的程序還會繼續執行,這裡就到了 App 執行緒的APT,這個方法裡有以下操作