首先,還是先將總體的順序寫出來
1、Laucher元件 首先向AMS(AndroidManagerService)傳送一個啟動Mainactivity的請求, 這個請求是程式間通訊的。
2、AMS首先將要啟動的MainActivity元件的資訊保留起來,然後向Laucher元件傳送一個進入終止狀態的程式通訊。
3、然後,Laucher元件會接收到AMS發來的中止請求,進入中止狀態, 然後再向AMS傳送訊息,告訴AMS 我已經進入中止狀態了,你請繼續做你的是事情,這樣AMS就能繼續進行啟動Aty的操作。
4、由於MainAty的啟動是在Lauther程式中啟動的,Lauther中止了,程式應用程式也就不存在了,然後AMS就會新啟動一個應用程式。
5、新的應用程式啟動後,就會告訴AMS 我(新的應用程式)已經啟動好了,然後發一個通訊請求給AMS。
6、接收到新應用程式發來的通訊後,AMS就會把第二步保留的元件資訊 傳遞給新的程式,然後新的程式就可以靠這些資訊去啟動MainAty。
上一篇啟動過程分析完了第一步,這一篇來分析第二步。也是先放原始碼。
public void startActivityForResult(Intent intent, int requestCode, 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());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
final View decor = mWindow != null ? mWindow.peekDecorView() : null;
if (decor != null) {
decor.cancelPendingInputEvents();
}
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
複製程式碼
我們單獨把這段程式碼拿出來分析
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());
}
複製程式碼
可以看到,這裡面呼叫了Instrument類,並且執行了execStartActivity()這個方法。
我麼先簡單瞭解一下這個Instrument類的作用。
Instrument類的主要作用:他用來監控,應用程式和系統之間的互動操作。
OK,現在可以看一下里面的引數,有一個mMainThread.這個mMainThread是Activity的一個成員變數ActivityThread,系統每開啟一個應用,都會初始化一個ActivityThread的例項,並且傳給每個應用的父親Activity(這個父親Activity就是我們的每一個繼承的Activity),然後看一下mMainThread.getApplicationThread()這個,好的 ,看一下ActivityThread的原始碼裡面這個方法。
public ApplicationThread getApplicationThread()
{
return mAppThread;
}
複製程式碼
返回的是一個mAppThread,這個Application其實就是一個IBinder的本地物件。有興趣的道友可以看一下原始碼,會呼叫mAppThread.asBinder方法,可以驗證這一點。這個mAppThread物件可以和Launcher通訊,在執行了execStartActivity()之後就會通過binder通知Launcher進入停止狀態。
在這裡,作者羅老師強調了一個地方,就是這個mToken,檢視原始碼知道,這個mToken是個IBinder型別的成員變數,他是一個IBinder的代理物件,指向了,AMS中,一個型別為ActivityRecord的本地物件。每一個啟動的Activity元件,在AMS中都有一個對應的ActivityRecord的物件,這個ActivityRecord物件,是用來維護對應的Activity的執行狀態以及資訊。
到這個地方,第二部就完成了。
OK 繼續深入execStartActivity()這個方法。先看原始碼
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
//主要過程放在IApplication中執行
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
//這裡查詢Activity 是否存在
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
//這裡是真正開啟Activity的地方
//這個ActivityManagerNative.getDefault()是AMS的代理物件,呼叫startActivity來將activity啟動起來
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
複製程式碼
我們著重看這段程式碼
//這裡是真正開啟Activity的地方
//這個ActivityManagerNative.getDefault()是AMS的代理物件,呼叫startActivity來將activity啟動起來
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
複製程式碼
可以看到,在execStartActivity裡面,呼叫了ActivityManagerNative.getDefault(),那這個ActivityManagerNative.getDefault()返回的是什麼呢?看一下原始碼。
static public IActivityManager getDefault() {
return gDefault.get();
}
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;
}
};
複製程式碼
這個返回的是一個IActivityManager物件,這個IAM 實際上是AMS(AndroidManagerService)的代理物件,然後通過呼叫它的startActivity來通知AMS將一個Activity元件啟動起來。
第二篇先寫到這裡,一點一點消化。