做爲Android開發的你,對Activity的使用確定是再熟悉不過了,在使用過程當中,你是否浮現過一個疑問:java
系統是如何管理這些Activity的?
沒錯,該文將與你一塊兒探索ActivityManagerService(如下簡寫爲AMS),看它是如何管理Activity的。android
該文主要圍繞如下三方面來討論:shell
先基本瞭解下AMS是什麼?數據結構
AMS的初始化,這裏我打算拿API 19(Android 4.4) 和 API 25(Android 7.1.1)的源碼進行對比。ide
在API 19源碼中,隨着SystemServer類main()方法的調用,實例化了內部類ServerThread的對象:oop
代碼1.1 (來源: SystemServer.java): public static void main(String[] args) { ......(省略了一小戳代碼) ServerThread thr = new ServerThread(); thr.initAndLoop(); }
咱們繼續看內部類ServerThread的initAndLoop()方法,看到這方法不得不吐槽一番,整個方法竟有長達1000+行代碼,真不知道這碼農是否是屁股癢了:this
代碼1.2 (來源: SystemServer.java): public void initAndLoop() { ...... context = ActivityManagerService.main(factoryTest); ...... ActivityManagerService.setSystemProcess(); }
該方法但是很是的強大哦,諸多系統級的服務都在此初始化,如AMS、PowerManagerService、WindowManagerService、NetworkManagementService等等,有興趣的能夠去細細品味源碼。
好了,繼續重點,調用ActivityManagerService的靜態方法main(),便可獲得AMS的上下文。spa
代碼1.3 (來源: ActivityManagerService.java): public static final Context main(int factoryTest) { // 建立了一個AThread線程,並開啓 AThread thr = new AThread(); thr.start(); synchronized (thr) { while (thr.mService == null) { try { thr.wait(); } catch (InterruptedException e) { } } } ActivityManagerService m = thr.mService; mSelf = m; ActivityThread at = ActivityThread.systemMain(); mSystemThread = at; Context context = at.getSystemContext(); m.mContext = context; ...... return context; }
這段代碼,不知道你有沒有發現,雖然它開啓了Athread線程,可是它立馬又進入了等待狀態,這是爲何呢?默默想10秒鐘。.net
由於下面須要使用到AMS的對象,若是AMS的對象還未初始化,咱們貿然使用,那確定會致使系統宕機。因此,可想而知,AThread中確定對AMS進行了實例化,那等待的線程如何去喚醒它呢?答案就在下面,繼續看看線程AThread的實現:線程
代碼1.4 (來源: ActivityManagerService.java): static class AThread extends Thread { ActivityManagerService mService; public AThread() { super("ActivityManager"); } @Override public void run() { ...... // 實例化了AMS對象 ActivityManagerService m = new ActivityManagerService(); synchronized (this) { mService = m; notifyAll(); } ...... } }
以上代碼中,實例化了AMS對象並賦值給mService,notifyAll()的職責就是對等待的AThread線程進行喚醒,此時便可跳出代碼1.3中的while循環,然後返回context。
而後調用ActivityManagerService.setSystemProcess();便可向Server Manager註冊,到此AMS的整個啓動流程到此結束。
剛咱們一塊兒瞭解了在API 19下的AMS啓動流程,那和API 25下的源碼相比較,有何改變呢?下面一塊兒來看看吧。
一樣是SystemServer類的main()方法,可是一行簡單代碼了事。
代碼1.5 (來源: SystemServer.java): public static void main(String[] args) { new SystemServer().run(); }
代碼1.6 (來源: SystemServer.java): private void run() { ...... // 在這裏啓動各類系統級服務 startBootstrapServices(); startCoreServices(); startOtherServices(); ...... }
代碼1.7 (來源: SystemServer.java): private void startBootstrapServices() { ...... // 這裏直接經過SystemServiceManager直接開啓AMS mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); ...... }
代碼1.8 (來源: ActivityManagerService.java): public static final class Lifecycle extends SystemService { private final ActivityManagerService mService; public Lifecycle(Context context) { super(context); // 獲得了AMS的實例 mService = new ActivityManagerService(context); } @Override public void onStart() { mService.start(); } public ActivityManagerService getService() { return mService; } }
看見沒,API 25的源碼相比API 19來講,通俗易懂,給贊,因此也無需多作解釋了,有興趣的能夠打開源碼仔細研究哦。
Stack意爲堆棧,做爲Activity的堆棧,主要仍是由如下三大部分組成。
該枚舉類定義的各類狀態和Activity的生命週期有着千絲萬縷的關係。
代碼2.1 (來源: ActivityStack.java): enum ActivityState { INITIALIZING, // 初始化中 RESUMED, // 恢復 PAUSING, // 暫停中 PAUSED, // 已暫停 STOPPING, // 中止中 STOPPED, // 已中止 FINISHING, // 完成中 DESTROYING, // 銷燬中 DESTROYED // 已銷燬 }
在Activity Stack中定義了一些ArrayList,用來保存特定狀態的Activity,好比:
代碼2.2 (來源: ActivityStack.java): ArrayList<TaskRecord> mTaskHistory; ArrayList<TaskGroup> mValidateAppTokens; ArrayList<ActivityRecord> mLRUActivities; ArrayList<ActivityRecord> mNoAnimActivities; ArrayList<ActivityRecord> mStoppingActivities; ArrayList<ActivityRecord> mFinishingActivities; ......
代碼2.3 (來源: ActivityStack.java): ActivityRecord mPausingActivity = null; ActivityRecord mLastPausedActivity = null; ActivityRecord mLastNoHistoryActivity = null; ActivityRecord mResumedActivity = null; ActivityRecord mLastStartedActivity = null; ......
正由於有了這三大部分,AMS便可經過Activity Stack實現了對系統組件的記錄、管理以及查詢功能。
小技巧:
在控制檯輸入如下命令,便可查看Activity Stack的信息
adb shell dumpsys activity
Activity Task的數據結構相似堆棧,遵循「先入後出」的原則,它負責裝載執行同一任務的Activity實例集合,下面咱們將拿Activity的四種launchMode來具體講解。
相信不少人對Activity的launchMode都有所瞭解,可是在使用的時候總會有些含糊不清,以下圖:
對各啓動模式的特色有所瞭解以後,接下來就逐一進行剖析。
從上圖Task的變化便可看出,每次操做都會將新的實例壓入棧頂,返回的時候剔除棧頂元素,全部操做都在同一個Task中完成。
經過在控制檯輸入adb shell dumpsys activity,就會打印諸多堆棧信息,從中咱們能夠找到如下信息便可印證上述結論:
當將OneActivity在AndroidManifest.xml中配置以下:
代碼3.2 : <activity android:name=".OneActivity" android:launchMode="singleTop">
兩種狀況打印日誌以下:
在上圖中,除將OneActivity的啓動模式設置爲SingleTask外,其他都默認。當咱們在ThreeActivity中打開OneActivity的時候,由於在Task中已經存在了OneActivity的實例,因此會直接將Intent經過onNewIntent傳遞給已存在的實例,而且會將它上面的其它全部實例從該堆棧中剔除,將本身暴露在棧頂。
咱們來看看控制檯打印的堆棧信息變化:
從上圖能夠看出,TwoActivity會獨佔一個新的Task,而且不容許其它實例加入進來。咱們來看看控制檯的日誌信息:
到此,Activity的四種啓動模式就講解完了。
縱觀全篇,咱們始終圍繞「AMS的啓動流程」、「Activity Stack介紹」和「Activity Task介紹」三方面來展開討論,若有疏漏,望批評指正。