大家好,今天想與大家一起分享的是Activity。我們平時接觸的最多的就是Activity了,作為四大組件中最為重要的老大,Activity究竟是如何啟動的呢?這篇文章將會從源碼的角度為大家進行全方位的解析,為了方便大家理解整個的過程,我會用流程圖的方式將整個過程串起來,希望對大家有所幫助。 ...
歡迎訪問我的個人博客,原文鏈接:http://wensibo.top/2017/07/03/Binder/ ,未經允許不得轉載!
大家好,今天想與大家一起分享的是Activity。我們平時接觸的最多的就是Activity了,作為四大組件中最為重要的老大,Activity究竟是如何啟動的呢?這篇文章將會從源碼的角度為大家進行全方位的解析,為了方便大家理解整個的過程,我會用流程圖的方式將整個過程串起來,希望對大家有所幫助。
開始吧!
一般我們啟動Activity有兩種方法,這裡我就不再詳細說這兩種方法的用法了,不過他們都是調用了同樣的一個邏輯startActivity
。所以我們分析Activity的啟動流程就從這個方法開始。
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
可以看到儘管startActivity()有多種重載方式,但是最終調用的還是startActivityForResult
,所以我們只需要看startActivityForResult裡面的實現邏輯即可。這裡需要註意的一點就是調用了startActivityForResult方法時傳入的一個參數為-1
,為什麼是-1呢?還記得我們如果需要下一個Activity返回數據給目前這個Activity的時候都是調用startActivityForResult方法,不會去調用startActivity,因為startActivity儘管最後還是調用startActivityForResult,但是他設置了requestCode參數為-1,二在startActivityForResult方法中會判斷requestCode是否大於等於0,如果小於0就不會返回結果,因此我們都會選擇startActivityForResult方法以取回結果,並且設置其code參數大於等於0。下麵我們來看看startActivityForResult的實現:
public void startActivityForResult(
@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {
//mParent是一個Activity對象,表示該Activity是否由父Activity啟動
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方法中,首先會判斷該Activity是否由父Activity啟動,即mParent,如果他是第一個Activity,就會調用Instrumentation的execStartActivity
方法,這裡再看一下判斷requestCode的邏輯:
if (requestCode >= 0) {
mStartedActivity = true;
}
可以看到在這裡確實判斷了requestCode的大小,大於等於0的時候才會返回結果,否則是不會的。
繼續說回execStartActivity
方法,這裡就是正真執行Activity啟動的操作,解釋一下他的幾個參數:
this
,為啟動Activity的對象mMainThread.
getApplicationThread(),為Binder對象,是主進程的context對象token
,也是一個Binder對象,指向了服務端一個ActivityRecord對象target
,為啟動的Activityintent
,啟動的Intent對象requestCode
,請求碼options
,參數
這裡的第一個Binder對象在我們的整個分析過程中將扮演者非常重要的作用,如果你對Binder不熟悉的話,請到這裡瞭解有關Binder機制的內容。
接下來是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;
}
這裡最重要的就是調用了ActivityManagerNative.getDefault().startActivity()
,但是ActivityManagerNative.getDefault()是什麼東西呢?我們繼續看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;
}
};
可以看到其中聲明瞭一個Singleton封裝類,其類型是IActivityManager,註意到其中調用了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返回了一個ActivityManagerProxy對象,也就是說ActivityManagerNative.getDefault()返回的就是一個ActivityManagerProxy
對象,通過之前的BInder機制的文章我們可以知道Proxy是運行在客戶端的,客戶端通過將參數寫入Proxy類,接著Proxy就會通過Binder去遠程調用服務端的具體方法,因此,我們只是借用ActivityManagerProxy來調用ActivityManagerService的方法,他們之間的關係如下所示:
到目前為止Activity的啟動流程就是如下所示了,可以看到Activity的啟動邏輯來到了AMS中。
在AMS中啟動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中直接調用了startActivityAsUser方法,而在startActivityAsUser中則是調用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;
}
這個方法中主要構造了ActivityManagerService端的Activity對象:ActivityRecord,並根據Activity的啟動模式執行了相關邏輯。然後調用了startActivityUncheckedLocked方法,而在startActivityUncheckedLocked中則調用了startActivityUncheckedLocked方法,startActivityUncheckedLocked方法則會調用startActivityLocked方法,startActivityLocked又會調用resumeTopActivitiesLocked方法,其最後調用了resumeTopActivityLocked方法。
經過一系列的調用之後,最終來到了startPausingLocked方法,它會執行Activity的onPause方法,從而結束當前的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;
}
...
}
這裡有一個很重要的地方就是prev.app.thread
,其實他就是一個IApplicationThread類型的對象,而ApplicationThread則是ActivityThread的一個內部類,它繼承了IApplicationThread,並且都是Binder對象,所以說Appcation是一個客戶端,而ActivityThread中是一個服務端,到現在為止,Activity的調用來到了ActivityThread中,如下圖所示:
在ActivityThread中pause掉當前Activity
在ActivityThread中則是調用了schedulePauseActivity來執行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來發送消息,消息類型為PAUSE_ACTIVITY_FINISHING,那接下來就應該看收到消息之後如何來處理了,
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;
}
}
可以看到在方法內部通過調用performPauseActivity方法來實現對當前Activity的onPause生命周期方法的回調,具體是調用了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;
}
可以看到最終是調用了Activity的onPause()方法,接著我們回到handlePauseActivity的第二個方法ActivityManagerNative.getDefault().activityPaused(token)
,這是應用進程告訴服務進程,當前的Activity已經執行完成onPause方法了,其最後會調用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);
}
}
}
}
可以看到經過了一系列的邏輯之後,又調用了resumeTopActivitiesLocked方法,而在該方法中則是調用了startSpecificActivityLocked 來啟動新的Activity。來看看目前的流程圖:
啟動新的Activity
在startSpecificActivityLocked方法中,其實現細節則是和調用Activity的pause方法一樣,都是通過Handler機制,發送一個啟動Activity的消息,接著處理該消息最後啟動Activity。其調用的是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對象終於創建出來了,可以看到其過程是使用反射機制創建的,而反射機制在Android系統中的應用也是隨處可見。在接下來的過程中還會繼續執行Activity的onCreate等一系列的生命周期方法。
最後再來看一下整個過程最終的流程圖: