It's right time to learn Android's Framework !html
一個App是怎麼啓動起來的?java
App的程序入口究竟是哪裏?android
Launcher究竟是什麼神奇的東西?web
據說還有個AMS的東西,它是作什麼的?設計模式
Binder是什麼?他是如何進行IPC通訊的?瀏覽器
Activity生命週期究竟是何時調用的?被誰調用的?服務器
等等...架構
你是否是還有不少相似的疑問一直沒有解決?不要緊,這篇文章將結合源碼以及大量的優秀文章,站在巨人的肩膀上,更加通俗的來試着解釋一些問題。可是畢竟源碼繁多、經驗有限,文中難免會出現一些紕漏甚至是錯誤,還懇請你們指出,互相學習。app
瞭解從手機開機第一個zygote進程建立,到點擊桌面上的圖標,進入一個App的完整流程,而且從源碼的角度瞭解到一個Activity的生命週期是怎麼回事。框架
瞭解到ActivityManagerService(即AMS)、ActivityStack、ActivityThread、Instrumentation等Android framework中很是重要的基礎類的做用,即相互間的關係。
瞭解AMS與ActivityThread之間利用Binder進行IPC通訊的過程,瞭解AMS和ActivityThread在控制Activity生命週期起到的做用和相互之間的配合。
瞭解Activity相關的framework層的其餘瑣碎問題
這篇文章我決定採用一問一答的方式進行。
其實在這以前,我試過把每一個流程的代碼調用過程,用粘帖代碼的方式寫在文章裏,可是寫完一部分以後,發現因爲代碼量太大,整篇文章和老太太的裹腳布同樣——又臭又長,雖然每一個重要的操做能夠顯示出詳細調用過程,可是太關注於細節範兒致使從總體上不能很好的把握。因此在原來的基礎智商進行了修改,對關鍵的幾個步驟進行終點介紹,力求語言簡潔,重點突出,從而讓你們在更高的層次上對framework層有個認識,而後結合後面我給出的參考資料,你們就能夠更加快速,更加高效的瞭解這一塊的總體架構。
咱們下面的文章將圍繞着這幾個類進行介紹。可能你第一次看的時候,印象不深,不過不要緊,當你隨着我讀完這篇文章的時候,我會在最後再次列出這些對象的功能,相信那時候你會對這些類更加的熟悉和深入。
ActivityManagerService,簡稱AMS,服務端對象,負責系統中全部Activity的生命週期
ActivityThread,App的真正入口。當開啓App以後,會調用main()開始運行,開啓消息循環隊列,這就是傳說中的UI線程或者叫主線程。與ActivityManagerServices配合,一塊兒完成Activity的管理工做。
ApplicationThread,用來實現ActivityManagerService與ActivityThread之間的交互。在ActivityManagerService須要管理相關Application中的Activity的生命週期時,經過ApplicationThread的代理對象與ActivityThread通信。
ApplicationThreadProxy,是ApplicationThread在服務器端的代理,負責和客戶端的ApplicationThread通信。AMS就是經過該代理與ActivityThread進行通訊的。
Instrumentation,每個應用程序只有一個Instrumentation對象,每一個Activity內都有一個對該對象的引用。Instrumentation能夠理解爲應用進程的管家,ActivityThread要建立或暫停某個Activity時,都須要經過Instrumentation來進行具體的操做。
ActivityStack,Activity在AMS的棧管理,用來記錄已經啓動的Activity的前後關係,狀態信息等。經過ActivityStack決定是否須要啓動新的進程。
ActivityRecord,ActivityStack的管理對象,每一個Activity在AMS對應一個ActivityRecord,來記錄Activity的狀態以及其餘的管理信息。其實就是服務器端的Activity對象的映像。
TaskRecord,AMS抽象出來的一個"任務"的概念,是記錄ActivityRecord的棧,一個"Task"包含若干個ActivityRecord。AMS用TaskRecord確保Activity啓動和退出的順序。若是你清楚Activity的4種launchMode,那麼對這個概念應該不陌生。
下面將按照App啓動過程的前後順序,一問一答,來解釋一些事情。
讓咱們開始吧!
首先,你以爲這個單詞眼熟不?當你的程序Crash的時候,打印的紅色log下面一般帶有這一個單詞。
zygote意爲"受精卵"。Android是基於Linux系統的,而在Linux中,全部的進程都是由init進程直接或者是間接fork出來的,zygote進程也不例外。
在Android系統裏面,zygote是一個進程的名字。Android是基於Linux System的,當你的手機開機的時候,Linux的內核加載完成以後就會啓動一個叫"init"的進程。在Linux System裏面,全部的進程都是由init進程fork出來的,咱們的zygote進程也不例外。
咱們都知道,每個App其實都是
一個單獨的dalvik虛擬機
一個單獨的進程
因此當系統裏面的第一個zygote進程運行以後,在這以後再開啓App,就至關於開啓一個新的進程。而爲了實現資源共用和更快的啓動速度,Android系統開啓新進程的方式,是經過fork第一個zygote進程實現的。因此說,除了第一個zygote進程,其餘應用所在的進程都是zygote的子進程,這下你明白爲何這個進程叫"受精卵"了吧?由於就像是一個受精卵同樣,它能快速的分裂,而且產生遺傳物質同樣的細胞!
首先我要告訴你的是,SystemServer也是一個進程,並且是由zygote進程fork出來的。
知道了SystemServer的本質,咱們對它就不算太陌生了,這個進程是Android Framework裏面兩大很是重要的進程之一——另一個進程就是上面的zygote進程。
爲何說SystemServer很是重要呢?由於系統裏面重要的服務都是在這個進程裏面開啓的,好比ActivityManagerService、PackageManagerService、WindowManagerService等等,看着是否是都挺眼熟的?
那麼這些系統服務是怎麼開啓起來的呢?
在zygote開啓的時候,會調用ZygoteInit.main()進行初始化
public static void main(String argv[]) {
...ignore some code...
//在加載首個zygote的時候,會傳入初始化參數,使得startSystemServer = true
boolean startSystemServer = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
...ignore some code...
//開始fork咱們的SystemServer進程
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
...ignore some code...
}
咱們看下startSystemServer()作了些什麼
/**留着這個註釋,就是爲了說明SystemServer確實是被fork出來的 * Prepare the arguments and fork for the system server process. */
private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException {
...ignore some code...
//留着這段註釋,就是爲了說明上面ZygoteInit.main(String argv[])裏面的argv就是經過這種方式傳遞進來的
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
//確實是fuck出來的吧,我沒騙你吧~不對,是fork出來的 -_-|||
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
handleSystemServerProcess(parsedArgs);
}
return true;
}
ActivityManagerService,簡稱AMS,服務端對象,負責系統中全部Activity的生命週期。
ActivityManagerService進行初始化的時機很明確,就是在SystemServer進程開啓的時候,就會初始化ActivityManagerService。從下面的代碼中能夠看到
public final class SystemServer {
//zygote的主入口
public static void main(String[] args) {
new SystemServer().run();
}
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
}
private void run() {
...ignore some code...
//加載本地系統服務庫,並進行初始化
System.loadLibrary("android_servers");
nativeInit();
// 建立系統上下文
createSystemContext();
//初始化SystemServiceManager對象,下面的系統服務開啓都須要調用SystemServiceManager.startService(Class<T>),這個方法經過反射來啓動對應的服務
mSystemServiceManager = new SystemServiceManager(mSystemContext);
//開啓服務
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
...ignore some code...
}
//初始化系統上下文對象mSystemContext,並設置默認的主題,mSystemContext其實是一個ContextImpl對象。調用ActivityThread.systemMain()的時候,會調用ActivityThread.attach(true),而在attach()裏面,則建立了Application對象,並調用了Application.onCreate()。
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
//在這裏開啓了幾個核心的服務,由於這些服務之間相互依賴,因此都放在了這個方法裏面。
private void startBootstrapServices() {
...ignore some code...
//初始化ActivityManagerService
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
//初始化PowerManagerService,由於其餘服務須要依賴這個Service,所以須要儘快的初始化
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// 如今電源管理已經開啓,ActivityManagerService負責電源管理功能
mActivityManagerService.initPowerManagement();
// 初始化DisplayManagerService
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
//初始化PackageManagerService
mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
...ignore some code...
}
}
通過上面這些步驟,咱們的ActivityManagerService對象已經建立好了,而且完成了成員變量初始化。並且在這以前,調用createSystemContext()建立系統上下文的時候,也已經完成了mSystemContext和ActivityThread的建立。注意,這是系統進程開啓時的流程,在這以後,會開啓系統的Launcher程序,完成系統界面的加載與顯示。
你是否會好奇,我爲何說AMS是服務端對象?下面我給你介紹下Android系統裏面的服務器和客戶端的概念。
其實服務器客戶端的概念不只僅存在於Web開發中,在Android的框架設計中,使用的也是這一種模式。服務器端指的就是全部App共用的系統服務,好比咱們這裏提到的ActivityManagerService,和前面提到的PackageManagerService、WindowManagerService等等,這些基礎的系統服務是被全部的App公用的,當某個App想實現某個操做的時候,要告訴這些系統服務,好比你想打開一個App,那麼咱們知道了包名和MainActivity類名以後就能夠打開
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName(packageName, className);
intent.setComponent(cn);
startActivity(intent);
可是,咱們的App經過調用startActivity()並不能直接打開另一個App,這個方法會經過一系列的調用,最後仍是告訴AMS說:"我要打開這個App,我知道他的住址和名字,你幫我打開吧!"因此是AMS來通知zygote進程來fork一個新進程,來開啓咱們的目標App的。這就像是瀏覽器想要打開一個超連接同樣,瀏覽器把網頁地址發送給服務器,而後仍是服務器把須要的資源文件發送給客戶端的。
知道了Android Framework的客戶端服務器架構以後,咱們還須要瞭解一件事情,那就是咱們的App和AMS(SystemServer進程)還有zygote進程分屬於三個獨立的進程,他們之間如何通訊呢?
App與AMS經過Binder進行IPC通訊,AMS(SystemServer進程)與zygote經過Socket進行IPC通訊。
那麼AMS有什麼用呢?在前面咱們知道了,若是想打開一個App的話,須要AMS去通知zygote進程,除此以外,其實全部的Activity的開啓、暫停、關閉都須要AMS來控制,因此咱們說,AMS負責系統中全部Activity的生命週期。
在Android系統中,任何一個Activity的啓動都是由AMS和應用程序進程(主要是ActivityThread)相互配合來完成的。AMS服務統一調度系統中全部進程的Activity啓動,而每一個Activity的啓動過程則由其所屬的進程具體來完成。
這樣說你可能仍是以爲比較抽象,不要緊,下面有一部分是專門來介紹AMS與ActivityThread如何一塊兒合做控制Activity的生命週期的。
當咱們點擊手機桌面上的圖標的時候,App就由Launcher開始啓動了。可是,你有沒有思考過Launcher究竟是一個什麼東西?
Launcher本質上也是一個應用程序,和咱們的App同樣,也是繼承自Activity
packages/apps/Launcher2/src/com/android/launcher2/Launcher.java
public final class Launcher extends Activity implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, View.OnTouchListener {
}
Launcher實現了點擊、長按等回調接口,來接收用戶的輸入。既然是普通的App,那麼咱們的開發經驗在這裏就仍然適用,好比,咱們點擊圖標的時候,是怎麼開啓的應用呢?若是讓你,你怎麼作這個功能呢?捕捉圖標點擊事件,而後startActivity()發送對應的Intent請求唄!是的,Launcher也是這麼作的,就是這麼easy!
那麼究竟是處理的哪一個對象的點擊事件呢?既然Launcher是App,而且有界面,那麼確定有佈局文件呀,是的,我找到了佈局文件launcher.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher" android:id="@+id/launcher">
<com.android.launcher2.DragLayer android:id="@+id/drag_layer" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true">
<!-- Keep these behind the workspace so that they are not visible when we go into AllApps -->
<include android:id="@+id/dock_divider" layout="@layout/workspace_divider" android:layout_marginBottom="@dimen/button_bar_height" android:layout_gravity="bottom" />
<include android:id="@+id/paged_view_indicator" layout="@layout/scroll_indicator" android:layout_gravity="bottom" android:layout_marginBottom="@dimen/button_bar_height" />
<!-- The workspace contains 5 screens of cells -->
<com.android.launcher2.Workspace android:id="@+id/workspace" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingStart="@dimen/workspace_left_padding" android:paddingEnd="@dimen/workspace_right_padding" android:paddingTop="@dimen/workspace_top_padding" android:paddingBottom="@dimen/workspace_bottom_padding" launcher:defaultScreen="2" launcher:cellCountX="@integer/cell_count_x" launcher:cellCountY="@integer/cell_count_y" launcher:pageSpacing="@dimen/workspace_page_spacing" launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left" launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right">
<include android:id="@+id/cell1" layout="@layout/workspace_screen" />
<include android:id="@+id/cell2" layout="@layout/workspace_screen" />
<include android:id="@+id/cell3" layout="@layout/workspace_screen" />
<include android:id="@+id/cell4" layout="@layout/workspace_screen" />
<include android:id="@+id/cell5" layout="@layout/workspace_screen" />
</com.android.launcher2.Workspace>
...ignore some code...
</com.android.launcher2.DragLayer>
</FrameLayout>
爲了方便查看,我刪除了不少代碼,從上面這些咱們應該能夠看出一些東西來:Launcher大量使用<include/>
標籤來實現界面的複用,並且定義了不少的自定義控件實現界面效果,dock_divider從佈局的參數聲明上能夠猜出,是底部操做欄和上面圖標佈局的分割線,而paged_view_indicator則是頁面指示器,和App首次進入的引導頁下面的界面引導是同樣的道理。固然,咱們最關心的是Workspace這個佈局,由於註釋裏面說在這裏麪包含了5個屏幕的單元格,想必你也猜到了,這個就是在首頁存放咱們圖標的那五個界面(不一樣的ROM會作不一樣的DIY,數量不固定)。
接下來,咱們應該打開workspace_screen佈局,看看裏面有什麼東東。
workspace_screen.xml
<com.android.launcher2.CellLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingStart="@dimen/cell_layout_left_padding" android:paddingEnd="@dimen/cell_layout_right_padding" android:paddingTop="@dimen/cell_layout_top_padding" android:paddingBottom="@dimen/cell_layout_bottom_padding" android:hapticFeedbackEnabled="false" launcher:cellWidth="@dimen/workspace_cell_width" launcher:cellHeight="@dimen/workspace_cell_height" launcher:widthGap="@dimen/workspace_width_gap" launcher:heightGap="@dimen/workspace_height_gap" launcher:maxGap="@dimen/workspace_max_gap" />
裏面就一個CellLayout,也是一個自定義佈局,那麼咱們就能夠猜到了,既然能夠存放圖標,那麼這個自定義的佈局頗有多是繼承自ViewGroup或者是其子類,實際上,CellLayout確實是繼承自ViewGroup。在CellLayout裏面,只放了一個子View,那就是ShortcutAndWidgetContainer。從名字也能夠看出來,ShortcutAndWidgetContainer這個類就是用來存放快捷圖標和__Widget小部件__的,那麼裏面放的是什麼對象呢?
在桌面上的圖標,使用的是BubbleTextView對象,這個對象在TextView的基礎之上,添加了一些特效,好比你長按移動圖標的時候,圖標位置會出現一個背景(不一樣版本的效果不一樣),因此咱們找到BubbleTextView對象的點擊事件,就能夠找到Launcher如何開啓一個App了。
除了在桌面上有圖標以外,在程序列表中點擊圖標,也能夠開啓對應的程序。這裏的圖標使用的不是BubbleTextView對象,而是PagedViewIcon對象,咱們若是找到它的點擊事件,就也能夠找到Launcher如何開啓一個App。
其實說這麼多,和今天的主題隔着十萬八千里,上面這些東西,你有興趣就看,沒興趣就直接跳過,不知道不影響這篇文章閱讀。
BubbleTextView的點擊事件在哪裏呢?我來告訴你:在Launcher.onClick(View v)裏面。
/** * Launches the intent referred by the clicked shortcut */
public void onClick(View v) {
...ignore some code...
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// Open shortcut
final Intent intent = ((ShortcutInfo) tag).intent;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
intent.setSourceBounds(new Rect(pos[0], pos[1],
pos[0] + v.getWidth(), pos[1] + v.getHeight()));
//開始開啓Activity咯~
boolean success = startActivitySafely(v, intent, tag);
if (success && v instanceof BubbleTextView) {
mWaitingForResume = (BubbleTextView) v;
mWaitingForResume.setStayPressed(true);
}
} else if (tag instanceof FolderInfo) {
//若是點擊的是圖標文件夾,就打開文件夾
if (v instanceof FolderIcon) {
FolderIcon fi = (FolderIcon) v;
handleFolderClick(fi);
}
} else if (v == mAllAppsButton) {
...ignore some code...
}
}
從上面的代碼咱們能夠看到,在桌面上點擊快捷圖標的時候,會調用
startActivitySafely(v, intent, tag);
那麼從程序列表界面,點擊圖標的時候會發生什麼呢?實際上,程序列表界面使用的是AppsCustomizePagedView對象,因此我在這個類裏面找到了onClick(View v)。
com.android.launcher2.AppsCustomizePagedView.java
/** * The Apps/Customize page that displays all the applications, widgets, and shortcuts. */
public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements View.OnClickListener, View.OnKeyListener, DragSource, PagedViewIcon.PressedCallback, PagedViewWidget.ShortPressListener, LauncherTransitionable {
@Override
public void onClick(View v) {
...ignore some code...
if (v instanceof PagedViewIcon) {
mLauncher.updateWallpaperVisibility(true);
mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
} else if (v instanceof PagedViewWidget) {
...ignore some code..
}
}
}
能夠看到,調用的是
mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
和上面同樣!這叫什麼?這叫異曲同工!
因此我們如今又明白了一件事情:無論從哪裏點擊圖標,調用的都是Launcher.startActivitySafely()。
下面咱們就能夠一步步的來看一下Launcher.startActivitySafely()到底作了什麼事情。
boolean startActivitySafely(View v, Intent intent, Object tag) {
boolean success = false;
try {
success = startActivity(v, intent, tag);
} catch (ActivityNotFoundException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
}
return success;
}
調用了startActivity(v, intent, tag)
boolean startActivity(View v, Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
boolean useLaunchAnimation = (v != null) &&
!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
if (useLaunchAnimation) {
if (user == null || user.equals(android.os.Process.myUserHandle())) {
startActivity(intent, opts.toBundle());
} else {
launcherApps.startMainActivity(intent.getComponent(), user,
intent.getSourceBounds(),
opts.toBundle());
}
} else {
if (user == null || user.equals(android.os.Process.myUserHandle())) {
startActivity(intent);
} else {
launcherApps.startMainActivity(intent.getComponent(), user,
intent.getSourceBounds(), null);
}
}
return true;
} catch (SecurityException e) {
...
}
return false;
}
這裏會調用Activity.startActivity(intent, opts.toBundle()),這個方法熟悉嗎?這就是咱們常常用到的Activity.startActivity(Intent)的重載函數。並且因爲設置了
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
因此這個Activity會添加到一個新的Task棧中,並且,startActivity()調用的實際上是startActivityForResult()這個方法。
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
因此咱們如今明確了,Launcher中開啓一個App,其實和咱們在Activity中直接startActivity()基本同樣,都是調用了Activity.startActivityForResult()。
還記得前面說過的Instrumentation對象嗎?每一個Activity都持有Instrumentation對象的一個引用,可是整個進程只會存在一個Instrumentation對象。當startActivityForResult()調用以後,實際上仍是調用了mInstrumentation.execStartActivity()
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
...ignore some code...
} else {
if (options != null) {
//當如今的Activity有父Activity的時候會調用,可是在startActivityFromChild()內部實際仍是調用的mInstrumentation.execStartActivity()
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
...ignore some code...
}
下面是mInstrumentation.execStartActivity()的實現
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...ignore some code...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
因此當咱們在程序中調用startActivity()的時候,實際上調用的是Instrumentation的相關的方法。
Instrumentation意爲"儀器",咱們先看一下這個類裏面包含哪些方法吧
(圖片省略)
咱們能夠看到,這個類裏面的方法大多數和Application和Activity有關,是的,這個類就是完成對Application和Activity初始化和生命週期的工具類。好比說,我單獨挑一個callActivityOnCreate()讓你看看
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
對activity.performCreate(icicle);這一行代碼熟悉嗎?這一行裏面就調用了傳說中的Activity的入口函數onCreate(),不信?接着往下看
Activity.performCreate()
final void performCreate(Bundle icicle) {
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
沒騙你吧,onCreate在這裏調用了吧。可是有一件事情必須說清楚,那就是這個Instrumentation類這麼重要,爲啥我在開發的過程當中,沒有發現他的蹤影呢?
是的,Instrumentation這個類很重要,對Activity生命週期方法的調用根本就離不開他,他能夠說是一個大管家,可是,這個大管家比較害羞,是一個女的,管內無論外,是老闆娘~
那麼你可能要問了,老闆是誰呀?
老闆固然是大名鼎鼎的ActivityThread了!
ActivityThread你都沒據說過?那你確定據說過傳說中的UI線程吧?是的,這就是UI線程。咱們前面說過,App和AMS是經過Binder傳遞信息的,那麼ActivityThread就是專門與AMS的外交工做的。
AMS說:"ActivityThread,你給我暫停一個Activity!"ActivityThread就說:"沒問題!"而後轉身和Instrumentation說:"老婆,AMS讓暫停一個Activity,我這裏忙着呢,你快去幫我把這事辦了把~"因而,Instrumentation就去把事兒搞定了。
因此說,AMS是董事會,負責指揮和調度的,ActivityThread是老闆,雖說家裏的事本身說了算,可是須要遵從AMS的指揮,而Instrumentation則是老闆娘,負責家裏的大事小事,可是通常不拋頭露面,聽一家之主ActivityThread的安排。
前面咱們說到,在調用startActivity()的時候,實際上調用的是
mInstrumentation.execStartActivity()
可是到這裏還沒完呢!裏面又調用了下面的方法
ActivityManagerNative.getDefault() .startActivity
這裏的ActivityManagerNative.getDefault返回的就是ActivityManagerService的遠程接口,即ActivityManagerProxy。
怎麼知道的呢?往下看
public abstract class ActivityManagerNative extends Binder implements IActivityManager {
//從類聲明上,咱們能夠看到ActivityManagerNative是Binder的一個子類,並且實現了IActivityManager接口
static public IActivityManager getDefault() {
return gDefault.get();
}
//經過單例模式獲取一個IActivityManager對象,這個對象經過asInterface(b)得到
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
}
//最終返回的仍是一個ActivityManagerProxy對象
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
//這裏面的Binder類型的obj參數會做爲ActivityManagerProxy的成員變量保存爲mRemote成員變量,負責進行IPC通訊
return new ActivityManagerProxy(obj);
}
}
再看ActivityManagerProxy.startActivity(),在這裏面作的事情就是IPC通訊,利用Binder對象,調用transact(),把全部須要的參數封裝成Parcel對象,向AMS發送數據進行通訊。
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
Binder本質上只是一種底層通訊方式,和具體服務沒有關係。爲了提供具體服務,Server必須提供一套接口函數以便Client經過遠程訪問使用各類服務。這時一般採用Proxy設計模式:將接口函數定義在一個抽象類中,Server和Client都會以該抽象類爲基類實現全部接口函數,所不一樣的是Server端是真正的功能實現,而Client端是對這些函數遠程調用請求的包裝。
爲了更方便的說明客戶端和服務器之間的Binder通訊,下面以ActivityManagerServices和他在客戶端的代理類ActivityManagerProxy爲例。
ActivityManagerServices和ActivityManagerProxy都實現了同一個接口——IActivityManager。
class ActivityManagerProxy implements IActivityManager{}
public final class ActivityManagerService extends ActivityManagerNative{}
public abstract class ActivityManagerNative extends Binder implements IActivityManager{}
雖然都實現了同一個接口,可是代理對象ActivityManagerProxy並不會對這些方法進行真正地實現,ActivityManagerProxy只是經過這種方式對方法的參數進行打包(由於都實現了相同接口,因此能夠保證同一個方法有相同的參數,即對要傳輸給服務器的數據進行打包),真正實現的是ActivityManagerService。
可是這個地方並非直接由客戶端傳遞給服務器,而是經過Binder驅動進行中轉。其實我對Binder驅動並不熟悉,咱們就把他當作一箇中轉站就OK,客戶端調用ActivityManagerProxy接口裏面的方法,把數據傳送給Binder驅動,而後Binder驅動就會把這些東西轉發給服務器的ActivityManagerServices,由ActivityManagerServices去真正的實施具體的操做。
可是Binder只能傳遞數據,並不知道是要調用ActivityManagerServices的哪一個方法,因此在數據中會添加方法的惟一標識碼,好比前面的startActivity()方法:
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
...ignore some code...
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
上面的START_ACTIVITY_TRANSACTION就是方法標示,data是要傳輸給Binder驅動的數據,reply則接受操做的返回值。
即
客戶端:ActivityManagerProxy=====>Binder驅動=====>ActivityManagerService:服務器
並且因爲繼承了一樣的公共接口類,ActivityManagerProxy提供了與ActivityManagerService同樣的函數原型,使用戶感受不出Server是運行在本地仍是遠端,從而能夠更加方便的調用這些重要的系統服務。
可是!這裏Binder通訊是單方向的,即從ActivityManagerProxy指向ActivityManagerService的,若是AMS想要通知ActivityThread作一些事情,應該咋辦呢?
仍是經過Binder通訊,不過是換了另一對,換成了ApplicationThread和ApplicationThreadProxy。
客戶端:ApplicationThread<=====Binder驅動<=====ApplicationThreadProxy:服務器
他們也都實現了相同的接口IApplicationThread
private class ApplicationThread extends ApplicationThreadNative {}
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread{}
class ApplicationThreadProxy implements IApplicationThread {}
剩下的就沒必要多說了吧,和前面同樣。
OK,至此,點擊桌面圖標調用startActivity(),終於把數據和要開啓Activity的請求發送到了AMS了。說了這麼多,其實這些都在一瞬間完成了,下面我們研究下AMS到底作了什麼。
注:前方有高能的方法調用鏈,若是你如今累了,請先喝杯咖啡或者是上趟廁所休息下
AMS收到startActivity的請求以後,會按照以下的方法鏈進行調用
調用startActivity()
@Override
public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
調用startActivityAsUser()
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
...ignore some code...
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, userId, null, null);
}
在這裏又出現了一個新對象ActivityStackSupervisor,經過這個類能夠實現對ActivityStack的部分操做。
final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, WaitResult outResult, Configuration config, Bundle options, int userId, IActivityContainer iContainer, TaskRecord inTask) {
...ignore some code...
int res = startActivityLocked(caller, intent, resolvedType, aInfo,
voiceSession, voiceInteractor, resultTo, resultWho,
requestCode, callingPid, callingUid, callingPackage,
realCallingPid, realCallingUid, startFlags, options,
componentSpecified, null, container, inTask);
...ignore some code...
}
繼續調用startActivityLocked()
final int startActivityLocked(IApplicationThread caller, Intent intent, String resolvedType, ActivityInfo aInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, Bundle options, boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container, TaskRecord inTask) {
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);
if (err < 0) {
notifyActivityDrawnForKeyguard();
}
return err;
}
調用startActivityUncheckedLocked(),此時要啓動的Activity已經經過檢驗,被認爲是一個正當的啓動請求。
終於,在這裏調用到了ActivityStack的startActivityLocked(ActivityRecord r, boolean newTask,boolean doResume, boolean keepCurTransition, Bundle options)。
ActivityRecord表明的就是要開啓的Activity對象,裏面分裝了不少信息,好比所在的ActivityTask等,若是這是首次打開應用,那麼這個Activity會被放到ActivityTask的棧頂,
final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, Bundle options, TaskRecord inTask) {
...ignore some code...
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
...ignore some code...
return ActivityManager.START_SUCCESS;
}
調用的是ActivityStack.startActivityLocked()
final void startActivityLocked(ActivityRecord r, boolean newTask, boolean doResume, boolean keepCurTransition, Bundle options) {
//ActivityRecord中存儲的TaskRecord信息
TaskRecord rTask = r.task;
...ignore some code...
//若是不是在新的ActivityTask(也就是TaskRecord)中的話,就找出要運行在的TaskRecord對象
TaskRecord task = null;
if (!newTask) {
boolean startIt = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
task = mTaskHistory.get(taskNdx);
if (task.getTopActivity() == null) {
// task中的全部Activity都結束了
continue;
}
if (task == r.task) {
// 找到了
if (!startIt) {
task.addActivityToTop(r);
r.putInHistory();
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
r.userId, r.info.configChanges, task.voiceSession != null,
r.mLaunchTaskBehind);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
ActivityOptions.abort(options);
return;
}
break;
} else if (task.numFullscreen > 0) {
startIt = false;
}
}
}
...ignore some code...
// Place a new activity at top of stack, so it is next to interact
// with the user.
task = r.task;
task.addActivityToTop(r);
task.setFrontOfTask();
...ignore some code...
if (doResume) {
mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
}
}
靠!這來回折騰什麼呢!從ActivityStackSupervisor到ActivityStack,又調回ActivityStackSupervisor,這究竟是在折騰什麼玩意啊!!!
淡定...淡定...我知道你也在內心罵娘,世界如此美妙,你卻如此暴躁,這樣很差,很差...
來來來,我們繼續哈,剛纔說到哪裏了?哦,對,我們一塊兒看下StackSupervisor.resumeTopActivitiesLocked(this, r, options)
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions) {
if (targetStack == null) {
targetStack = getFocusedStack();
}
// Do targetStack first.
boolean result = false;
if (isFrontStack(targetStack)) {
result = targetStack.resumeTopActivityLocked(target, targetOptions);
}
...ignore some code...
return result;
}
我...已無力吐槽了,又調回ActivityStack去了...
ActivityStack.resumeTopActivityLocked()
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
} finally {
inResumeTopActivity = false;
}
return result;
}
我們堅持住,看一下ActivityStack.resumeTopActivityInnerLocked()到底進行了什麼操做
final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
...ignore some code...
//找出還沒結束的首個ActivityRecord
ActivityRecord next = topRunningActivityLocked(null);
//若是一個沒結束的Activity都沒有,就開啓Launcher程序
if (next == null) {
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
// Only resume home if on home display
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
}
//先須要暫停當前的Activity。由於咱們是在Lancher中啓動mainActivity,因此當前mResumedActivity!=null,調用startPausingLocked()使得Launcher進入Pausing狀態
if (mResumedActivity != null) {
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
}
}
在這個方法裏,prev.app爲記錄啓動Lancher進程的ProcessRecord,prev.app.thread爲Lancher進程的遠程調用接口IApplicationThead,因此能夠調用prev.app.thread.schedulePauseActivity,到Lancher進程暫停指定Activity。
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming, boolean dontWait) {
if (mPausingActivity != null) {
completePauseLocked(false);
}
...ignore some code...
if (prev.app != null && prev.app.thread != null)
try {
mService.updateUsageStats(prev, false);
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, dontWait);
} catch (Exception e) {
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
} else {
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
...ignore some code...
}
在Lancher進程中消息傳遞,調用ActivityThread.handlePauseActivity(),最終調用ActivityThread.performPauseActivity()暫停指定Activity。接着經過前面所說的Binder通訊,通知AMS已經完成暫停的操做。
ActivityManagerNative.getDefault().activityPaused(token).
上面這些調用過程很是複雜,源碼中各類條件判斷讓人眼花繚亂,因此說若是你沒記住也不要緊,你只要記住這個流程,理解了Android在控制Activity生命週期時是如何操做,以及是經過哪幾個關鍵的類進行操做的就能夠了,之後遇到相關的問題之道從哪塊下手便可,這些過程我雖然也是擼了一遍,但仍是記不清。
不要使用startActivityForResult(intent,RESULT_OK)
這是由於startActivity()是這樣實現的
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
而
public static final int RESULT_OK = -1;
因此
startActivityForResult(intent,RESULT_OK) = startActivity()
你不可能從onActivityResult()裏面收到任何回調。而這個問題是至關難以被發現的,就是由於這個坑,我工做一年多來第一次加班到9點 (ˇˍˇ)
是ActivityThread.main()。
是在ActivityThread初始化的時候,就已經建立消息循環了,因此在主線程裏面建立Handler不須要指定Looper,而若是在其餘線程使用Handler,則須要單獨使用Looper.prepare()和Looper.loop()建立消息循環。
public static void main(String[] args) {
...ignore some code...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
...ignore some code...
}
也是在ActivityThread.main()的時候,再具體點呢,就是在thread.attach(false)的時候。
看你的表情,不信是吧!凱子哥帶你溜溜~
咱們先看一下ActivityThread.attach()
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
//普通App進這裏
if (!system) {
...ignore some code...
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}
} else {
//這個分支在SystemServer加載的時候會進入,經過調用
// private void createSystemContext() {
// ActivityThread activityThread = ActivityThread.systemMain();
//}
// public static ActivityThread systemMain() {
// if (!ActivityManager.isHighEndGfx()) {
// HardwareRenderer.disable(true);
// } else {
// HardwareRenderer.enableForegroundTrimming();
// }
// ActivityThread thread = new ActivityThread();
// thread.attach(true);
// return thread;
// }
}
}
這裏須要關注的就是mgr.attachApplication(mAppThread),這個就會經過Binder調用到AMS裏面對應的方法
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
而後就是
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
mCoreSettingsObserver.getCoreSettingsLocked());
}
thread是IApplicationThread,實際上就是ApplicationThread在服務端的代理類ApplicationThreadProxy,而後又經過IPC就會調用到ApplicationThread的對應方法
private class ApplicationThread extends ApplicationThreadNative {
public final void bindApplication(String processName, ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, ProfilerInfo profilerInfo, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {
...ignore some code...
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableOpenGlTrace = enableOpenGlTrace;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
sendMessage(H.BIND_APPLICATION, data);
}
}
咱們須要關注的其實就是最後的sendMessage(),裏面有函數的編號H.BIND_APPLICATION,而後這個Messge會被H這個Handler處理
private class H extends Handler {
...ignore some code...
public static final int BIND_APPLICATION = 110;
...ignore some code...
public void handleMessage(Message msg) {
switch (msg.what) {
...ignore some code...
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...ignore some code...
}
}
最後就在下面這個方法中,完成了實例化,撥那個企鵝經過mInstrumentation.callApplicationOnCreate實現了onCreate()的調用。
private void handleBindApplication(AppBindData data) {
try {
...ignore some code...
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
...ignore some code...
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
}
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) { }
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}
data.info是一個LoadeApk對象。
LoadeApk.data.info.makeApplication()
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
initializeJavaContextClassLoader();
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) { }
mActivityThread.mAllApplications.add(app);
mApplication = app;
//傳進來的是null,因此這裏不會執行,onCreate在上一層執行
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
}
}
...ignore some code...
}
return app;
}
因此最後仍是經過Instrumentation.makeApplication()實例化的,這個老闆娘真的很厲害呀!
static public Application newApplication(Class<?> clazz, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
並且經過反射拿到Application對象以後,直接調用attach(),因此attach()調用是在onCreate()以前的。
下面的這些文章都是這方面比較精品的,但願你抽出時間研究,這可能須要花費很長時間,可是若是你想進階爲中高級開發者,這一步是必須的。
再次感謝下面這些文章的做者的分享精神。
http://blog.csdn.net/universus/article/details/6211589
http://blog.csdn.net/luoshengyang/article/details/6768304
http://blog.csdn.net/xieqibao/article/details/6581975
http://www.th7.cn/Program/Android/201404/187670.shtml
http://blog.csdn.net/myarrow/article/details/14224273
http://blog.csdn.net/luoshengyang/article/details/6747696#comments
http://laokaddk.blog.51cto.com/368606/1206840
http://blog.csdn.net/yangwen123/article/details/35987609
http://www.xuebuyuan.com/2172927.html
http://blog.csdn.net/yangwen123/article/details/35987609
http://mobile.51cto.com/hot-312129.htm
http://www.cnblogs.com/mythou/p/3187881.html
OK,到這裏,這篇文章算是告一段落了,咱們再回頭看看一開始的幾個問題,你還困惑嗎?
一個App是怎麼啓動起來的?
App的程序入口究竟是哪裏?
Launcher究竟是什麼神奇的東西?
據說還有個AMS的東西,它是作什麼的?
Binder是什麼?他是如何進行IPC通訊的?
Activity生命週期究竟是何時調用的?被誰調用的?
再回過頭來看看這些類,你還迷惑嗎?
ActivityManagerServices,簡稱AMS,服務端對象,負責系統中全部Activity的生命週期
ActivityThread,App的真正入口。當開啓App以後,會調用main()開始運行,開啓消息循環隊列,這就是傳說中的UI線程或者叫主線程。與ActivityManagerServices配合,一塊兒完成Activity的管理工做
ApplicationThread,用來實現ActivityManagerService與ActivityThread之間的交互。在ActivityManagerService須要管理相關Application中的Activity的生命週期時,經過ApplicationThread的代理對象與ActivityThread通信。
ApplicationThreadProxy,是ApplicationThread在服務器端的代理,負責和客戶端的ApplicationThread通信。AMS就是經過該代理與ActivityThread進行通訊的。
Instrumentation,每個應用程序只有一個Instrumentation對象,每一個Activity內都有一個對該對象的引用。Instrumentation能夠理解爲應用進程的管家,ActivityThread要建立或暫停某個Activity時,都須要經過Instrumentation來進行具體的操做。
ActivityStack,Activity在AMS的棧管理,用來記錄已經啓動的Activity的前後關係,狀態信息等。經過ActivityStack決定是否須要啓動新的進程。
ActivityRecord,ActivityStack的管理對象,每一個Activity在AMS對應一個ActivityRecord,來記錄Activity的狀態以及其餘的管理信息。其實就是服務器端的Activity對象的映像。
TaskRecord,AMS抽象出來的一個"任務"的概念,是記錄ActivityRecord的棧,一個"Task"包含若干個ActivityRecord。AMS用TaskRecord確保Activity啓動和退出的順序。若是你清楚Activity的4種launchMode,那麼對這個概念應該不陌生。
若是你還感到迷惑的話,就把這篇文章多讀幾遍吧,信息量可能比較多,須要慢慢消化~
做者:凱子哥
連接:http://www.jianshu.com/p/6037f6fda285