在日常開發(fā)中我們經(jīng)常從一個(gè)Activity跳轉(zhuǎn)到另一個(gè)Activity芳室,調(diào)用的代碼無非有以下兩種
startActivity(intent);
startActivityForResult(intent, requestCode);
其實(shí)startActivity()最終也會(huì)調(diào)用startActivityForResult()來實(shí)現(xiàn)界面的跳轉(zhuǎn),下面我們就從startActivityForResult()來梳理Activity的啟動(dòng)流程;
@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 {
startActivityForResult(intent, -1);
}
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
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());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
關(guān)鍵方法mInstrumentation.execStartActivity()斜做,返回回調(diào)結(jié)果场躯。Instrumentation拿來測試過的同學(xué)并不陌生谈为,這里且當(dāng)它是個(gè)黑科技工具。
進(jìn)入execStartActivity方法踢关。
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
...
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);
...
}
這里解釋下前4個(gè)參數(shù):
- who:正在啟動(dòng)該Activity的上下文
- contextThread:正在啟動(dòng)該Activity的上下文線程伞鲫,這里為ApplicationThread
- token:正在啟動(dòng)該Activity的標(biāo)識(shí)
- target:正在啟動(dòng)該Activity的Activity,也就是回調(diào)結(jié)果的Activity
我們先來看看下面的checkStartActivityResult方法签舞。
public static void checkStartActivityResult(int res, Object intent) {
if (res >= ActivityManager.START_SUCCESS) {
return;
}
switch (res) {
case ActivityManager.START_INTENT_NOT_RESOLVED:
case ActivityManager.START_CLASS_NOT_FOUND:
if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
throw new ActivityNotFoundException(
"Unable to find explicit activity class "
+ ((Intent)intent).getComponent().toShortString()
+ "; have you declared this activity in your AndroidManifest.xml?");
throw new ActivityNotFoundException(
"No Activity found to handle " + intent);
case ActivityManager.START_PERMISSION_DENIED:
throw new SecurityException("Not allowed to start activity "
+ intent);
case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
throw new AndroidRuntimeException(
"FORWARD_RESULT_FLAG used while also requesting a result");
case ActivityManager.START_NOT_ACTIVITY:
throw new IllegalArgumentException(
"PendingIntent is not an activity");
case ActivityManager.START_NOT_VOICE_COMPATIBLE:
throw new SecurityException(
"Starting under voice control not allowed for: " + intent);
case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
throw new IllegalStateException(
"Session calling startVoiceActivity does not match active session");
case ActivityManager.START_VOICE_HIDDEN_SESSION:
throw new IllegalStateException(
"Cannot start voice activity on a hidden session");
case ActivityManager.START_CANCELED:
throw new AndroidRuntimeException("Activity could not be started for "
+ intent);
default:
throw new AndroidRuntimeException("Unknown error code "
+ res + " when starting " + intent);
}
}
這些異常就是根據(jù)返回碼和intent拋出相應(yīng)異常秕脓,最熟悉的就是activity沒有在AndroidManifest里面注冊(cè)了。
在這個(gè)方法中儒搭,我們還發(fā)現(xiàn)了熟悉的字眼startActivity吠架,但調(diào)用者卻很陌生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");
...
IActivityManager am = asInterface(b);
...
return am;
}
};
static public IActivityManager asInterface(IBinder obj) {
...
return new ActivityManagerProxy(obj);
}
這樣看下來好像是ServiceManager構(gòu)建了一個(gè)key為activity的對(duì)象,該對(duì)象作為ActivityManagerProxy的參數(shù)實(shí)例化創(chuàng)建單例并get返回搂鲫。這里先不作解析傍药,繼續(xù)連接上面的流程ActivityManagerNative.getDefault().startActivity(…)。我們已經(jīng)知道startActivity方法其實(shí)是ActivityManagerProxy調(diào)的魂仍,我們?cè)賮砜纯础?/p>
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();
...
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
...
reply.recycle();
data.recycle();
return result;
}
我們通過代理類ActivityManagerProxy調(diào)用了startActivity方法拐辽,讓我們來搜尋一下AMS的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 bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,resulUserHandle.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 bOptions, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),userId, false, ALLOW_FULL_ONLY, "startActivity", null);
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,profilerInfo, null, null, bOptions, false, userId, null, null);
}
其中enforceNotIsolatedCaller方法是檢查是否屬于被隔離的對(duì)象擦酌。mUserController.handleIncomingUser檢查操作權(quán)限然后返回一個(gè)用戶id(涉及到Linux俱诸,有興趣的同學(xué)可以翻閱翻閱,這不是我們的重點(diǎn))赊舶,startActivityAsUser方法大概就是檢測下權(quán)限睁搭,然后返回由mActivityStarter(ActivityStarter赶诊,可以這么說,關(guān)于Activity啟動(dòng)的所有信息都在這了介袜,然后根據(jù)信息把Activity具體分配到哪個(gè)任務(wù)棧)調(diào)用的startActivityMayWait方法甫何。
繼續(xù)跟蹤ActivityStarter的startActivityMayWait的方法出吹。
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, IActivityManager.WaitResult outResult, Configuration config,
Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
...
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
...
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
...
final ProcessRecord heavy = mService.mHeavyWeightProcess;
if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
|| !heavy.processName.equals(aInfo.processName))) {
...
}
...
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask);
...
}
final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {
...
ProcessRecord callerApp = null;
...
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
...
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
options, sourceRecord);
...
err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true, options, inTask);
...
return err;
}
繼續(xù)跟進(jìn)核心方法 startActivityUnchecked()
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
computeLaunchingTaskFlags();
...
mIntent.setFlags(mLaunchFlags);
mReusedActivity = getReusableIntentActivity();
...
boolean newTask = false;
...
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
...
}
...
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
...
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
...
}
先看setInitialState
private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
boolean doResume, int startFlags, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
reset();
mStartActivity = r;
mIntent = r.intent;
mOptions = options;
mCallingUid = r.launchedFromUid;
mSourceRecord = sourceRecord;
mVoiceSession = voiceSession;
...
mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
mLaunchFlags = adjustLaunchFlagsToDocumentMode(
r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
...
}
這里初始化了比較重要的mStartActivity遇伞,mIntent,mCallingUid捶牢,mSourceRecord鸠珠,mLaunchFlags。mLaunchFlags用來記錄我們Activity的啟動(dòng)方式秋麸,省略部分都是根據(jù)啟動(dòng)方式來初始化一堆變量或進(jìn)行操作渐排。
final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
ActivityOptions options) {
...
mWindowManager.setAppVisibility(r.appToken, true);
...
}
mWindowManager.setAppVisibility(r.appToken, true);這句話表示這個(gè)Activity已經(jīng)具備了顯示的條件。接下來我們長話短說灸蟆,大體來看已經(jīng)差不多了驯耻,通知后,我們會(huì)調(diào)用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法炒考,接著調(diào)ActivityStack的resumeTopActivityUncheckedLocked方法可缚,再調(diào)自己的resumeTopActivityInnerLocked方法,如果Activity已存在需要可見狀態(tài)斋枢,那么會(huì)調(diào)IApplicationThread的scheduleResumeActivity方法帘靡,且經(jīng)過一系列判斷可見Activity;反之調(diào)ActivityStackSupervisor的startSpecificActivityLocked的方法瓤帚,那么繼續(xù)會(huì)調(diào)realStartActivityLocked的方法
終于調(diào)ApplicationThread的scheduleLaunchActivity方法啦描姚!
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
看最后,handler發(fā)送message戈次,那么這個(gè)handler是什么呢轩勘?
private class H extends Handler {
...
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
}
}
private class H extends Handler {
...
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
}
}
我們直接看我們發(fā)的消息,它調(diào)用了ActivityThread的handleLaunchActivity方法怯邪。
WindowManagerGlobal.initialize();//初始化WMS
Activity a = performLaunchActivity(r, customIntent);//創(chuàng)建并啟動(dòng)
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;//取出組件信息绊寻,并一頓操作
...
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
//開始創(chuàng)建Activity實(shí)例,通過類加載器創(chuàng)建擎颖,看參數(shù)就知道了
...
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
//獲取Application
...
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
//與window建立關(guān)聯(lián)
...
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
//callActivityOnCreate->activity.performCreate->onCreate榛斯,之后就很熟悉了
...
}
}
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
//如果mApplication不為空則直接返回,這也是為什么Application為單例
...
Application app = null;
...
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
//創(chuàng)建Application搂捧,跟Activity一樣驮俗,都是用類加載器創(chuàng)建
...
mApplication = app;//保存下來
...
instrumentation.callApplicationOnCreate(app);
//callApplicationOnCreate->onCreate
...
}
總結(jié):
至此,activity就啟動(dòng)了允跑,至于activity啟動(dòng)之后王凑,又經(jīng)歷了哪些過程搪柑,可以看我的另一篇文章 Android 中的setContentView源碼解析