歡迎訪問我的個(gè)人博客煌妈,原文鏈接:http://wensibo.top/2017/07/05/Activity/ ,未經(jīng)允許不得轉(zhuǎn)載宣羊!
大家好璧诵,今天想與大家一起分享的是Activity。我們平時(shí)接觸的最多的就是Activity了仇冯,作為四大組件中最為重要的老大之宿,Activity究竟是如何啟動(dòng)的呢?這篇文章將會(huì)從源碼的角度為大家進(jìn)行全方位的解析苛坚,為了方便大家理解整個(gè)的過程比被,我會(huì)用流程圖的方式將整個(gè)過程串起來,希望對(duì)大家有所幫助泼舱。
開始吧等缀!
一般我們啟動(dòng)Activity有兩種方法,這里我就不再詳細(xì)說這兩種方法的用法了娇昙,不過他們都是調(diào)用了同樣的一個(gè)邏輯startActivity
尺迂。所以我們分析Activity的啟動(dòng)流程就從這個(gè)方法開始。
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
可以看到盡管startActivity()有多種重載方式冒掌,但是最終調(diào)用的還是startActivityForResult
噪裕,所以我們只需要看startActivityForResult里面的實(shí)現(xiàn)邏輯即可。這里需要注意的一點(diǎn)就是調(diào)用了startActivityForResult方法時(shí)傳入的一個(gè)參數(shù)為-1
股毫,為什么是-1呢膳音?還記得我們?nèi)绻枰乱粋€(gè)Activity返回?cái)?shù)據(jù)給目前這個(gè)Activity的時(shí)候都是調(diào)用startActivityForResult方法,不會(huì)去調(diào)用startActivity铃诬,因?yàn)閟tartActivity盡管最后還是調(diào)用startActivityForResult祭陷,但是他設(shè)置了requestCode參數(shù)為-1,二在startActivityForResult方法中會(huì)判斷requestCode是否大于等于0氧急,如果小于0就不會(huì)返回結(jié)果颗胡,因此我們都會(huì)選擇startActivityForResult方法以取回結(jié)果,并且設(shè)置其code參數(shù)大于等于0吩坝。下面我們來看看startActivityForResult的實(shí)現(xiàn):
public void startActivityForResult(
@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {
//mParent是一個(gè)Activity對(duì)象毒姨,表示該Activity是否由父Activity啟動(dòng)
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
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());
}
//這里就是判斷requestCode的邏輯
if (requestCode >= 0) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
在startActivityForResult方法中,首先會(huì)判斷該Activity是否由父Activity啟動(dòng)钉寝,即mParent弧呐,如果他是第一個(gè)Activity闸迷,就會(huì)調(diào)用Instrumentation的execStartActivity
方法,這里再看一下判斷requestCode的邏輯:
if (requestCode >= 0) {
mStartedActivity = true;
}
可以看到在這里確實(shí)判斷了requestCode的大小,大于等于0的時(shí)候才會(huì)返回結(jié)果俘枫,否則是不會(huì)的腥沽。
繼續(xù)說回execStartActivity
方法,這里就是正真執(zhí)行Activity啟動(dòng)的操作鸠蚪,解釋一下他的幾個(gè)參數(shù):
-
this
今阳,為啟動(dòng)Activity的對(duì)象 -
mMainThread.
getApplicationThread(),為Binder對(duì)象茅信,是主進(jìn)程的context對(duì)象 -
token
盾舌,也是一個(gè)Binder對(duì)象,指向了服務(wù)端一個(gè)ActivityRecord對(duì)象 -
target
蘸鲸,為啟動(dòng)的Activity -
intent
妖谴,啟動(dòng)的Intent對(duì)象 -
requestCode
,請(qǐng)求碼 -
options
酌摇,參數(shù)
這里的第一個(gè)Binder對(duì)象在我們的整個(gè)分析過程中將扮演者非常重要的作用膝舅,如果你對(duì)Binder不熟悉的話,請(qǐng)到這里了解有關(guān)Binder機(jī)制的內(nèi)容窑多。
接下來是execStartActivity
方法:
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
...
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) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
這里最重要的就是調(diào)用了ActivityManagerNative.getDefault().startActivity()
仍稀,但是ActivityManagerNative.getDefault()是什么東西呢?我們繼續(xù)看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;
}
};
可以看到其中聲明了一個(gè)Singleton封裝類怯伊,其類型是IActivityManager琳轿,注意到其中調(diào)用了asInterface
方法,接著看他做了什么耿芹?
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
//ActivityManagerProxy: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();
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;
}
可以看到asInterface返回了一個(gè)ActivityManagerProxy對(duì)象崭篡,也就是說ActivityManagerNative.getDefault()返回的就是一個(gè)ActivityManagerProxy
對(duì)象,通過之前的BInder機(jī)制的文章我們可以知道Proxy是運(yùn)行在客戶端的吧秕,客戶端通過將參數(shù)寫入Proxy類琉闪,接著Proxy就會(huì)通過Binder去遠(yuǎn)程調(diào)用服務(wù)端的具體方法,因此砸彬,我們只是借用ActivityManagerProxy來調(diào)用ActivityManagerService的方法颠毙,他們之間的關(guān)系如下所示:
到目前為止Activity的啟動(dòng)流程就是如下所示了,可以看到Activity的啟動(dòng)邏輯來到了AMS中砂碉。
在AMS中啟動(dòng)Activity
@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());
}
@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) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, false, userId, null, null);
}
在startActivity中直接調(diào)用了startActivityAsUser方法蛀蜜,而在startActivityAsUser中則是調(diào)用mStackSupervisor.startActivityMayWait方法:
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 ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
ActivityContainer container, TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
...
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);
...
return err;
}
這個(gè)方法中主要構(gòu)造了ActivityManagerService端的Activity對(duì)象:ActivityRecord,并根據(jù)Activity的啟動(dòng)模式執(zhí)行了相關(guān)邏輯增蹭。然后調(diào)用了startActivityUncheckedLocked方法滴某,而在startActivityUncheckedLocked中則調(diào)用了startActivityUncheckedLocked方法,startActivityUncheckedLocked方法則會(huì)調(diào)用startActivityLocked方法,startActivityLocked又會(huì)調(diào)用resumeTopActivitiesLocked方法霎奢,其最后調(diào)用了resumeTopActivityLocked方法户誓。
經(jīng)過一系列的調(diào)用之后,最終來到了startPausingLocked方法幕侠,它會(huì)執(zhí)行Activity的onPause方法帝美,從而結(jié)束當(dāng)前的Activity。
首先來看startPausingLocked方法:
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,boolean dontWait) {
...
if (prev.app != null && prev.app.thread != null) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
try {
EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
prev.userId, System.identityHashCode(prev),
prev.shortComponentName);
mService.updateUsageStats(prev, false);
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, dontWait);
} catch (Exception e) {
// Ignore exception, if process died other code will cleanup.
Slog.w(TAG, "Exception thrown during pause", e);
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
} else {
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
...
}
這里有一個(gè)很重要的地方就是prev.app.thread
晤硕,其實(shí)他就是一個(gè)IApplicationThread類型的對(duì)象悼潭,而ApplicationThread則是ActivityThread的一個(gè)內(nèi)部類,它繼承了IApplicationThread舞箍,并且都是Binder對(duì)象女责,所以說Appcation是一個(gè)客戶端,而ActivityThread中是一個(gè)服務(wù)端,到現(xiàn)在為止创译,Activity的調(diào)用來到了ActivityThread中,如下圖所示:
在ActivityThread中pause掉當(dāng)前Activity
在ActivityThread中則是調(diào)用了schedulePauseActivity來執(zhí)行pause操作:
public final void schedulePauseActivity(IBinder token, boolean finished,boolean userLeaving, int configChanges, boolean dontReport) {
sendMessage(
finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
token,
(userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
configChanges);
}
可以看到在schedulePauseActivity中則是通過handler來發(fā)送消息墙基,消息類型為PAUSE_ACTIVITY_FINISHING软族,那接下來就應(yīng)該看收到消息之后如何來處理了,
private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
if (userLeaving) {
performUserLeavingActivity(r);
}
r.activity.mConfigChangeFlags |= configChanges;
performPauseActivity(token, finished, r.isPreHoneycomb());
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}
// Tell the activity manager we have paused.
if (!dontReport) {
try {
ActivityManagerNative.getDefault().activityPaused(token);
} catch (RemoteException ex) {
}
}
mSomeActivitiesChanged = true;
}
}
可以看到在方法內(nèi)部通過調(diào)用performPauseActivity方法來實(shí)現(xiàn)對(duì)當(dāng)前Activity的onPause生命周期方法的回調(diào)残制,具體是調(diào)用了performPause方法:
final void performPause() {
mDoReportFullyDrawn = false;
mFragments.dispatchPause();
mCalled = false;
onPause();
mResumed = false;
if (!mCalled && getApplicationInfo().targetSdkVersion
>= android.os.Build.VERSION_CODES.GINGERBREAD) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onPause()");
}
mResumed = false;
}
可以看到最終是調(diào)用了Activity的onPause()方法立砸,接著我們回到handlePauseActivity的第二個(gè)方法ActivityManagerNative.getDefault().activityPaused(token)
,這是應(yīng)用進(jìn)程告訴服務(wù)進(jìn)程初茶,當(dāng)前的Activity已經(jīng)執(zhí)行完成onPause方法了颗祝,其最后會(huì)調(diào)用completePauseLocked方法:
private void completePauseLocked(boolean resumeNext) {
...
if (resumeNext) {
final ActivityStack topStack = mStackSupervisor.getFocusedStack();
if (!mService.isSleepingOrShuttingDown()) {
mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
} else {
mStackSupervisor.checkReadyForSleepLocked();
ActivityRecord top = topStack.topRunningActivityLocked(null);
if (top == null || (prev != null && top != prev)) {
// If there are no more activities available to run,
// do resume anyway to start something. Also if the top
// activity on the stack is not the just paused activity,
// we need to go ahead and resume it to ensure we complete
// an in-flight app switch.
mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);
}
}
}
}
可以看到經(jīng)過了一系列的邏輯之后,又調(diào)用了resumeTopActivitiesLocked方法恼布,而在該方法中則是調(diào)用了startSpecificActivityLocked 來啟動(dòng)新的Activity螺戳。來看看目前的流程圖:
啟動(dòng)新的Activity
在startSpecificActivityLocked方法中,其實(shí)現(xiàn)細(xì)節(jié)則是和調(diào)用Activity的pause方法一樣折汞,都是通過Handler機(jī)制倔幼,發(fā)送一個(gè)啟動(dòng)Activity的消息,接著處理該消息最后啟動(dòng)Activity爽待。其調(diào)用的是performLaunchActivity方法:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
...
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
...
return activity;
}
可以看到最終的Activity對(duì)象終于創(chuàng)建出來了损同,可以看到其過程是使用反射機(jī)制創(chuàng)建的,而反射機(jī)制在Android系統(tǒng)中的應(yīng)用也是隨處可見鸟款。在接下來的過程中還會(huì)繼續(xù)執(zhí)行Activity的onCreate等一系列的生命周期方法膏燃。
最后再來看一下整個(gè)過程最終的流程圖: