本平臺的文章更新會有延遲,你們能夠關注微信公衆號-顧林海,包括年末前會更新kotlin由淺入深系列教程,目前計劃在微信公衆號進行首發,若是你們想獲取最新教程,請關注微信公衆android
AMS(ActivityManagerService)的啓動是在SystemServer進程中啓動的,它的職責是用於和全部APP的四大組件進行通訊,Activity的啓動過程就是APP端與AMS端進行通訊,首先理解的一點是APP端與AMS是在兩個不一樣的進程中,所以APP端與AMS是經過跨進程通訊的。web
Launcher就是指手機的屏幕,同時它也是一個APP,只不過這是由製造商開發的,手指點擊屏幕的某個APP,這時APP啓動並打開首頁的界面,這一系列操做須要和AMS進行通訊才能完成,APP安裝(啓動)時,PackageManagerService從APK包的AndroidManifest文件中讀取四大組件的信息並保存下來。微信
下圖是Launcher與AMS的通訊時序圖:app
Launcher與APP是在兩個不一樣的進程中,他們之間的通訊是經過Binder完成的,點擊Launcher上的某個APP,這時會調用Launcher的startActivitySafely方法。ide
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
...
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//1
...
startActivity(intent, optsBundle);//2
...
}
複製代碼
上面代碼我省略了一些不過重要的,重點看上面兩行代碼,第一行給intent設置Flag爲Intent.FLAG_ACTIVITY_NEW_TASK,Activity會在新的任務棧中啓動,第二行代碼調用startActivity方法,很簡單,就是啓動APP中的Activity。函數
最終會調用Activity的startActivity方法,Intent中攜帶的就是須要啓動的APP的Activity信息。startActivity方法最終會調用startActivityForResult方法,代碼以下:oop
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@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);
}
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
...
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
...
}
複製代碼
Activity內部會保持一個對Instrumentation的引用,Instrumentation主要用來監控應用程序和系統的交互,在startActivityForResult方法中會調用Instrumentation的execStartActivity方法,在execStartActivity方法的第二個參數中,能夠看到一個mMainThread的變量,這是一個ActivityThread類型的變量,ActivityThread就是主線程,也就是咱們日常所說的UI線程,它是在APP啓動時建立的,表明APP應用程序,ActivityThread裏面有個main函數,是APP啓動時的入口。post
execStartActivity方法傳遞了兩個很重要的參數,mMainThread.getApplicationThread(Binder對象)將Launcher所在的進程傳遞了過去,這樣AMS知道是哪一個進程;還有一個比較重要的是mToken,它是Binder對象,表明Launcher這個Activity也經過Instrumentation傳給AMS,AMS查詢時,就知道誰向AMS發起了請求。ui
Instrumentation的execStartActivity代碼以下:this
public Instrumentation.ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {
...
try {
...
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
...
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
複製代碼
這裏經過ActivityManager的getService方法來獲取AMS的代理對象(Android 7.0是經過ActivityManagerNative的getDefault來獲取AMS的代理對象),返回一個類型爲IActivityManager,IActivityManager是一個接口,內部定義了四大組件的生命週期,
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
複製代碼
Singleton是一個單例類,內部經過ServiceManager取出一個activity的對象,經過IActivityManager.Stub.asInterface將它包裝成一個ActivityManagerProxy對象(AMP),IActivityManager.Stub.asInterface這段代碼是否是很熟悉,就是AIDL遠程代理,這裏獲取到的是AMS的代理對象。
AMP告訴AMS啓動哪一個APP,而且啓動的是哪一個Activity,AMS會檢查APP中的AndroidManifest文件,看看是否存在要啓動的Activity,若是不存在,就會拋出一個Activity not found的錯誤。AMS檢查到啓動的Activity存在,這時會告訴Launcher:「我要啓動Activity了」,Launcher會將它所在的進程傳給AMS,AMS會將它保存爲一個ActivityRecord對象,這個對象裏面有一個ApplicationThreadProxy,是一個Binder代理,AMS想要發送消息給Launcher,能夠經過ApplicationThreadProxy(ATP)來發送消息,ATP是APP端ApplicationThread(APT)的代理對象,用於AMS與APP端的通訊。
既然AMS知道了啓動的Activity,接下來就應該啓動Activity,在啓動Activity以前,AMS須要告訴Launcher「我要啓動了,你能夠暫停了「,時序圖以下:
中間經過ApplicationThreadProxy向APP端的ApplicationThread發送消息,ApplicationThread接受到AMS的消息後,調用ActivityThread的sendMessage方法,向Launcher的主線程消息隊列發送一個PAUSE_ACTIVITY消息。
@Override
public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, PendingTransactionActions pendingActions, String reason) {
//獲取Launcher的Activity
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
if (userLeaving) {
performUserLeavingActivity(r);
}
r.activity.mConfigChangeFlags |= configChanges;
performPauseActivity(r, finished, reason, pendingActions);
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}
mSomeActivitiesChanged = true;
}
}
複製代碼
handlePauseActivity方法中從mActivities集合中,獲取Launcher的Activity並讓他休眠。
到這裏Launcher與AMS之間的通訊就結束了,接下來的事情就是啓動APP中的Activity,由於是首次啓動,APP的進程不存在,須要建立一個新的進程,須要調用Process.start方法,而且指定了ActivityThread的main函數爲入口函數:
int pid=Process.start("android.app.ActivityThread",
mSimpleProcessManagement ? app.processName:gid,
debugFlags,
null);
複製代碼
爲新進程建立ActivityThread對象,也就是UI線程,同時執行入口函數main,其中建立一個主線程Looper,也就是MainLooper。
另外建立Application,主線程序會收到BIND_APPLICATION消息:
public void handleMessage(Message msg) {
...
switch (msg.what) {
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;
...
}
...
}
複製代碼
根據傳遞過來的ApplicationInfo建立一個對應的LoadedApk對象,而後建立ContextImpl對象,接着經過反射建立目標Application,並調用attach方法,將ContextImpl對象設置爲目標Application的上下文環境,最後調用Application的onCreate函數。
建立完APP後,APP端通知AMS建立完畢同時把ActivityThread對象發送給AMS,同時AMS端把ActivityThread對象轉換成一個ActivityThreadProxy對象,以後AMS能夠向APP端發送消息,經過ActivityThreadProxy這個代理對象。
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
複製代碼
ActivityThread接受到AMS的消息,在H中發送LAUNCH_ACTIVITY消息,調用handleLaunchActivity方法,在該方法中經過Instrumentation的newActivity方法,建立要啓動的Activity實例,爲這個Activity建立一個上下文Context對象,並與Activity關聯,經過Instrumentation的callActivityOnCreate方法,執行Activity的onCreate方法,從而啓動Activity,至此APP啓動完畢。
搜索微信「顧林海」公衆號,按期推送優質文章。