startActivity() 流程分析 (SDK源碼為28)
當我們從手機桌面點擊應用圖標時,這時候就會打開我們的應用程序弊仪,在這個過程中發(fā)生了什么事情灌曙,整個流程是怎么樣的?我們知道在Android中一個App就相當于一個進程缠俺,點擊應用icon時就相當于從一個進程跳轉(zhuǎn)到了另一進程。在這里就涉及到了跨進程通訊贷岸,Android系統(tǒng)中是通過Binder來實現(xiàn)進程通訊的壹士,是由ActivityThread
的內(nèi)部類ApplicationThread
來完成的,這里主要涉及到了三個階段:
第一階段:
ActivityA
通過Binder通訊告訴ActivityManagerService
要啟動ActivityB
第二階段:
ActivityManagerService
收到啟動ActivityB
的消息后偿警,會做一些列的判斷和準備工作躏救,比如構(gòu)造Intent,應用棧的處理,應用進程的創(chuàng)建等工作盒使,然后把任務交給ActivityB所在的進程第三階段:
ActivityB
所在進程收到任務消息后崩掘,會創(chuàng)建Activity并調(diào)用其生命周期方法
針對Android系統(tǒng)來說,手機桌面也是頁面少办,應用icon是這個頁面展示的數(shù)據(jù)苞慢;手機桌面是通過Launcher
類來實現(xiàn)的,Launcher繼承自Activity凡泣,手機廠商自定義桌面都是通過實現(xiàn)Launcher來實現(xiàn)的枉疼,我們首先來看它的onClick
方法,這里面記錄了我們點擊應用icon后的操作邏輯:
public void onClick(View v) {
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) { //點擊應用icon
final Intent intent = ((ShortcutInfo) tag).intent;
boolean success = startActivitySafely(v, intent, tag);
} else if (tag instanceof FolderInfo) {//點擊文件夾鞋拟,主要是應用分類
if (v instanceof FolderIcon) {
FolderIcon fi = (FolderIcon) v;
handleFolderClick(fi);
}
} else if (v == mAllAppsButton) {//點擊顯示所有應用icon
if (isAllAppsVisible()) {
showWorkspace(true);
} else {
onClickAllAppsButton(v);
}
}
}
這里我們主要關(guān)注點擊應用icon的邏輯處理骂维,因為后面兩種點擊邏輯處理最終都會調(diào)用點擊應用icon的梳理邏輯,接下來我們進入startActivitySafely()
方法
boolean startActivitySafely(View v, Intent intent, Object tag) {
boolean success = false;
try {
success = startActivity(v, intent, tag);
} catch (ActivityNotFoundException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
}
return success;
}
這個方法主要對startActivity()
進行了一層包裝贺纲,進行異常處理航闺,然后進入startActivity()
boolean startActivity(View v, Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //在新的任務棧中啟動
try {
UserHandle user = (UserHandle) intent.getParcelableExtra(ApplicationInfo.EXTRA_PROFILE);
LauncherApps launcherApps = (LauncherApps)
this.getSystemService(Context.LAUNCHER_APPS_SERVICE);
if (user == null || user.equals(android.os.Process.myUserHandle())) {
startActivity(intent, opts.toBundle()); //調(diào)用Activity的startActivity()
} else {
launcherApps.startMainActivity(intent.getComponent(), user,
intent.getSourceBounds(),
opts.toBundle());
}
return true;
} catch (SecurityException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
}
return false;
}
這里主要分了兩步走,我們首先看Activity#startActivity()
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
Activity#startActivity()
重寫了父類ContextWrapper
的startActivity()猴誊,然后調(diào)用了startActivityForResult()
,傳入-1的作用是不需要返回結(jié)果
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle 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());
}
}
以上代碼我只摘抄了主要部分潦刃,方便理解,在startActivityForResult中調(diào)用了Instrumentation#execStartActivity()
,這個Instrumentation
是用來監(jiān)控應用程序和系統(tǒng)交互的懈叹,mMainThread.getApplicationThread()
是一個IBinder接口乖杠,用于實現(xiàn)進程間通訊的。
public ActivityResult execStartActivity(Context who, IBinder contextThread ...) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
try {
int result = ActivityTaskManager.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);
}
}
可以發(fā)現(xiàn)澄成,在這里獲取了ActivityA
的IApplicationThread
胧洒,然后通過ActivityTaskManager獲取了ActivityManagerService,并調(diào)用了其startActivity
墨状,這一步實現(xiàn)了ActivityA
到ActivityManagerService
的過渡卫漫,啟動ActivityB
的任務就交由AMS來實現(xiàn)。
接下來我們來看Server端啟動Activity的流程肾砂,首先我們進入AMS#startActivity()
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,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
public final int startActivityAsUser() {
return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
.execute();
}
在這里我們獲取了一個ActivityStarter
列赎,然后采用Builder模式設(shè)置了一些參數(shù),最后調(diào)用了execute镐确;看名字這個ActivityStarter是專門用來啟動Activity的包吝,接下來我們進入這個類,查看execute做了什么處理
int execute() {
if (mRequest.mayWait) {
return startActivityMayWait(mRequest.caller, mRequest.callingUid,
mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup);
} else {
return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
mRequest.outActivity, mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup);
}
}
在startActivityMayWait
和startActivity
中主要做了解析Intent源葫,創(chuàng)建ActivityRecord诗越,創(chuàng)建TaskRecord等工作;最終這兩個方法都會調(diào)用ActivityStarter#startActivityUnchecked()
private int startActivityUnchecked() {
//啟動Flag計算
computeLaunchingTaskFlags();
//處理Task和Activity的進站操作
mTargetStack.startActivityLocked();
//處理棧頂Activity
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,mOptions);
}
boolean resumeFocusedStackTopActivityLocked() {
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || !r.isState(RESUMED)) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.isState(RESUMED)) {
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
上面幾個判斷最終都會調(diào)用ActivityStack#resumeTopActivityUncheckedLocked
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
boolean result = false;
result = resumeTopActivityInnerLocked(prev, options);
return result;
}
在ActivityStack#resumeTopActivityInnerLocked()
中會經(jīng)過一些列的判斷臼氨,最后調(diào)用ActivityStackSupervisor#startSpecificActivityLocked()
方法
void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
if (app != null && app.thread != null) {
realStartActivityLocked(r, app, andResume, checkConfig);
return;
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
在這里會判斷ActivityB所在的應用進程是否存在,如果進程不存在芭届,會先去創(chuàng)建進程储矩,最后會調(diào)用realStartActivityLocked
感耙,我們再進入ActivityStackSupervisor#realStartActivityLocked()
,查看做了什么邏輯
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
// Create activity launch transaction. 創(chuàng)建transaction
final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,r.appToken);
//添加Callback回調(diào)接口持隧,稍后會執(zhí)行
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r),
r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(),
r.compat,
r.launchedFromPackage,
task.voiceInteractor,
app.repProcState,
r.icicle,
r.persistentState,
results,
newIntents,
mService.isNextTransitionForward(),
profilerInfo));
// Schedule transaction. 執(zhí)行transaction
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
}
可以看到最后獲取了ClientLifecycleManager即硼,然后執(zhí)行了scheduleTransaction(),然后進入這個方法
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
}
在這里Transaction的client屡拨,這個client是IApplicationThread類型只酥,這個類是用于進程間通訊的,有可能這里會使用client來和AMS通信呀狼,后面會不會使用它裂允,我們向下分析就知道了,最后這個方法執(zhí)行了transaction.schedule()
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
果然這里使用利用client實現(xiàn)了ActivityB所在的進程和AMS所在進程進行通訊哥艇,調(diào)用了ActivityB所在進程的IApplicationThread
的scheduleTransaction()绝编,這里Activity啟動任務實現(xiàn)了從AMS到ActivityB所在進程的交接
這下startActivity任務來到第三階段,AMS通過Binder通信貌踏,把啟動ActivityB的任務交由ActivityB所在進程處理十饥,ActivityB所在進程的ApplicationThread
的scheduleTransaction()
方法被調(diào)用
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
在ActivityThread方法中會找不到scheduleTransaction,因為調(diào)用的是其父類ClientTransactionHandler#scheduleTransaction()
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
在這個方法中祖乳,先調(diào)用了preExecute()做了一些預處理工作逗堵,然后向ActivityThread所在線程的Handler發(fā)送了一條消息EXECUTE_TRANSACTION;這個時候直接查看這個名為H的Handler的handleMessage()
做了什么處理邏輯
public void handleMessage(Message msg) {
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
transaction.recycle();
}
break;
}
Handler在收到這條消息后眷昆,調(diào)用TransactionExecutor#execute()
public void execute(ClientTransaction transaction) {
executeCallbacks(transaction);
executeLifecycleState(transaction);
}
public void executeCallbacks(ClientTransaction transaction) {
final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
final int size = callbacks.size();
for (int i = 0; i < size; ++i) {
final ClientTransactionItem item = callbacks.get(i);
item.execute(mTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
}
}
這里會獲取到transaction的所有Callback對象蜒秤,然后依次執(zhí)行它們的execute方法,那么這些Callback是什么時候添加的呢隙赁?還記得我們創(chuàng)建Transaction的時候么垦藏,創(chuàng)建Transaction對象時,我們往里面添加了Callback對象LaunchActivityItem伞访,這里我們只需要查看LaunchActivityItem的execute做了什么處理就行 (LaunchActivityItem是繼承自ClientTransactionItem)
public void execute(ClientTransactionHandler client ...) {
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
}
這里調(diào)用了ClientTransactionHandler#handleLaunchActivity
掂骏,其實就是調(diào)用的ActivityThread的handleLaunchActivity(),因為ActivityThread是ClientTransactionHandler的實現(xiàn)類
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
WindowManagerGlobal.initialize();
final Activity a = performLaunchActivity(r, customIntent);
}
首先創(chuàng)建WindowManagerService厚掷,進行Window初始化相關(guān)操作弟灼;然后再調(diào)用performLaunchActivity()處理Activity的創(chuàng)建邏輯
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//第一步:創(chuàng)建Activity的Context
ContextImpl appContext = createBaseContextForActivity(r);
//第二步:創(chuàng)建Activity實例
Activity activity = null;
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
//第三步:獲取當前進程的application實例
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
//LoadedApk的makeApplication
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
//第三步:執(zhí)行Activity的attach方法
//創(chuàng)建PhoneWindow,設(shè)置mWindow#setCallback()冒黑,設(shè)置mWindowManager田绑,設(shè)置mApplication
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, r.configCallback);
//第四步:調(diào)用Activity的onCreate()
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
}
到此從ActivityA到ActivityB的啟動流程已經(jīng)完成,ActivityB成功啟動抡爹,并調(diào)用了其onCreate()掩驱,如還需要分析后續(xù)流程,就應該是View的繪制流程了
到最后,我們對這個流程做一個總結(jié):
- 第一步:無論是從桌面點擊應用圖標啟動Activity還是從ActivityA跳轉(zhuǎn)到ActivityB欧穴,其本質(zhì)都是從ActivityA跳轉(zhuǎn)到ActivityB民逼,通過調(diào)用startActivity方法,通過Binder機制把啟動Activity的任務交由AMS涮帘,由Instrumentation調(diào)用
AMS#startActivity()
- 第二步:AMS的startActivity()收到任務拼苍,經(jīng)過ActivityStarter,ActivityStack调缨,ActivityStackSupervisor的一系列處理疮鲫,最終由AMS調(diào)用目標Activity所在進程的ApplicationThread的scheduleTransaction()
- 第三步:在ActivityThread的ApplicationThread收到scheduleTransaction()任務后,經(jīng)過ActivityThread的一系列處理后調(diào)用handleLaunchActivity弦叶,進行Activity的創(chuàng)建等一系列工作俊犯,最后調(diào)用onCreate(),完成Activity的啟動