重溫四大組件第四篇,這裏分析一下Activity的啓動過程。Activity的啓動過程分爲兩種,一種是根Activity的啓動,另一種是普通Activity的啓動過程。根Activity也就是默認啓動的Activity(在AndroidMinifest.xml配置的啓動Activity)。普通Activity指的是除根Activity的其餘Activity。其中根Activity和普通Activity的啓動過程略有區別,根Activity的啓動過程涉及到了應用程序進程的啓動過程。java
接下來從根Activity的角度啓動來講。android
如下分析的代碼基於Android 9.0數據結構
咱們在看一些技術博客的時候常常會看到一些分析AMS的文章。AMS就是ActivityManagerService,顧名思義就是Activity的管理服務,但它不只僅管理Activity,其餘三個組件的啓動也經由AMS。同時,在看Activity的啓動過程以前,咱們應該瞭解一些Binder的知識。Binder是Android系統中一種跨進程通訊技術。在Activity的啓動過程當中就涉及到了Binder通訊的過程。app
Activity的啓動過程,能夠歸納爲Launcher到AMS(通過Binder通訊),從AMS到ApplicationThread(經過Binder通訊)。ide
以上介紹了AMS在Activity的啓動中承擔的做用。接下來,咱們再介紹一些在Activity啓動過程當中的一些其餘角色。函數
從ActivityStack的命名能夠看出這個是Activity棧相關的。它的做用是管理和記錄一個Activity棧的Activity。接下來咱們看下ActivityStack中有哪些屬性。post
名稱 | 類型 | 說明 |
---|---|---|
mService | ActivityManagerService | 目前AMS的引用 |
mRecentTasks | RecentTasks | 記錄一個最近使用的Activity列表 |
mPausingActivity | ActivityRecord | 目前中止狀態的Activity信息 |
mResumedActivity | ActivityRecord | 目前resume狀態的Activity信息 |
ActivityRecord是用來描述一個Activity的數據結構,它記錄了Activity的全部信息。學習
名稱 | 類型 | 說明 |
---|---|---|
service | ActivityManagerService | 目前AMS的引用 |
info | ActivityInfo | 主要記錄了Activity在Manifest文件中的配置信息 |
launchedFromPid | int | 啓動Activity進程的pid |
launchedFromUid | int | 啓動Activity進程的uid |
taskAffinity | String | Activity啓動後所在的task |
task | TaskRecord | 記錄了所在task的信息 |
app | ProcessRecord | 記錄了Activity啓動所在進程的信息 |
state | ActivityState | 當前Activity的狀態 |
theme | int | Activity的主題 |
TaskRecord是關於任務棧的描述。ui
名稱 | 類型 | 說明 |
---|---|---|
taskId | final int | 任務棧的惟一標識 |
affinity | String | 任務棧的名稱,也就是taskAffinity配置的名稱 |
intent | Intent | 啓動這個任務棧的Intent |
mActivities | ArrayList | 按照在任務棧中歷史順序排序的Activity |
mStack | ActivityStack | 任務棧所在的Activity棧 |
mService | ActivityManagerService | 目前AMS的引用 |
ProcessRecord是關於應用進程的描述。this
名稱 | 類型 | 說明 |
---|---|---|
uid | int | 進程的uid |
processName | String | 進程名稱 |
info | ApplicationInfo | 記錄應用程序信息 |
在上面介紹了Activity啓動過程當中關於Activity啓動過程當中的一些信息記錄。好比:Activity棧信息、任務棧信息以及進程信息等。
Activity的啓動過程是一個很複雜的過程,接下來的分析過程並不會把全部細節都分析到位。咱們分析Activity的啓動過程主要是爲了學習Android系統對Activity組件的管理過程以及對應用進程的調度。
咱們知道在Android系統中鎖呈現的桌面就是一個應用程序。當用戶點擊桌面上的應用圖標是就能夠啓動相應的應用程序。應用程序由Launcher啓動,調用startActivitySafely()方法。
/**Launcher.java**/
boolean startActivitySafely(Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
return true;
} catch (ActivityNotFoundException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
} catch (SecurityException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
}
return false;
}
複製代碼
能夠看到在startActivitySafely()中繼續調用startActivity()方法啓動Activity,而且在Intent中設置了flag爲FLAG_ACTIVITY_NEW_TASK表示Activity將在一個新的任務棧中啓動。這個方法就是在Activity中的。
/**Activity.java**/
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
複製代碼
這裏繼續調用了startActivityForResult(),而且requestCode爲-1表示Launcher不須要知道Activity的結果。
/**Activity.java**/
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
//繼續啓動Activity
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);
}
}
}
複製代碼
在這裏先判斷mParent是否爲null,而後根據結果選擇走那一步。若是跟代碼的話,能夠看到mParent在attach()方法中或者setParent()方法中賦值,在根Activity的狀況中mParent爲null。因此繼續調用 mInstrumentation.execStartActivity()。
/**Instrumentation.java**/
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, String target, Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
//......
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
//經過Binder接口獲取AMS對象
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target, requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
複製代碼
在上面的方法中繼續啓動Activity,在這裏咱們能夠看到經過ActivityManager.getService()咱們就獲取到了AMS對象。接下來,咱們看下AMS的獲取過程。
/**ActivityManager.java**/
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
複製代碼
在getService()方法中經過IActivityManagerSingleton獲取了AMS的對象。在建立IActivityManagerSingleton的方法中咱們能夠看到返回的是IActivityManager,IActivityManager就是使用了AIDL的方式生成的。
從這裏開始,Activity的啓動就開始在AMS中進行了。從上面的代碼能夠知道這個過程是經過Binder通訊方式進行的。
/**ActivityManagerService.java**/
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());
}
複製代碼
在ActivityManagerService中經過startActivity()方法繼續進行Activity的啓動。接下來咱們直接看最終的方法回調。
/**ActivityManagerService.java**/
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, boolean validateIncomingUser) {
//......
//從obtainStarter()中獲取了ActivityStarter對象
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) //設置mayWait標誌
.execute();
}
複製代碼
在上面的方法中,AMS經過startActivityAsUser()方法最終把Activity的啓動過程轉移到了ActivityStarter中。咱們直接看下ActivityStarter的execute()方法。
/**ActivityStarter**/
int execute() {
try {
if (mRequest.mayWait) {
return startActivityMayWait(mRequest.caller, mRequest.callingUid,
//....//);
} else {
return startActivity(mRequest.caller, mRequest.intent, //....//);
}
} finally {
onExecutionComplete();
}
}
複製代碼
這裏根據mRequest.mayWait(表示咱們應該等待啓動請求的結果。)中的標誌來判斷走哪一個邏輯分支。在上面的代碼中調用setMayWait(userId),這裏將mayWait設置爲true。那麼接下來咱們繼續看startActivityMayWait()方法。
private int startActivityMayWait(//....//) {
//......
// Collect information about the target of the Intent.
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo); //構建Activity的信息
synchronized (mService) {
final ActivityStack stack = mSupervisor.mFocusedStack; //獲取Activity棧的信息
stack.mConfigWillChange = globalConfig != null
&& mService.getGlobalConfiguration().diff(globalConfig) != 0;
//......
final ActivityRecord[] outRecord = new ActivityRecord[1]; //獲取Activity的信息
//繼續啓動Activity
int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
allowPendingRemoteAnimationRegistryLookup);
Binder.restoreCallingIdentity(origId);
//......
return res;
}
}
複製代碼
咱們繼續跟代碼,接下會調用
private int startActivity(//....//) {
//......
ProcessRecord callerApp = null; //獲取進程信息
if (caller != null) {
//caller是ActivityThread中的Binder接口,用過應用程序進程則不爲null
callerApp = mService.getRecordForAppLocked(caller); //獲取進程信息
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
}
}
//......
//建立啓動Activity的信息類
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, checkedOptions, sourceRecord);
if (outActivity != null) {
outActivity[0] = r;
}
final ActivityStack stack = mSupervisor.mFocusedStack; //獲取有焦點的Activity棧
//......
//繼續啓動Activity
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true /* doResume */, checkedOptions, inTask, outActivity);
}
複製代碼
在上面會看到根據IApplicationThread獲取應用進程信息,這裏若是應用進程沒有被建立的時候,IApplicationThread是null,而後接下來的步驟會建立應用程序進程,這裏再也不詳細說。接下來繼續進行Activity啓動的分析。
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) {
//......
int result = START_SUCCESS;
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mService.mWindowManager.executeAppTransition();
} else {
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
//這裏繼續啓動Activity
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
}
return START_SUCCESS;
}
複製代碼
接下來啓動Activity的過程轉到ActivityStackSupervisor中。
/**ActivityStackSupervisor**/
boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
//這裏從Activity棧中啓動
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
//......
return false;
}
複製代碼
上面的代碼中繼續啓動Activity,此次啓動過程轉到ActivityStack中。
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
//......省略代碼
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
if (mResumedActivity != null) {
//這裏若是mResumedActivity不爲null,就中止mResumedActivity
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, next, false);
}
//next是ActivityRecord對象,next.app是ProcessRecord對象,next.app.thread是IApplicationThread
if (next.app != null && next.app.thread != null) {
//若是都不爲null,說明應用進程已經被建立
//......
synchronized(mWindowManager.getWindowManagerLock()) {
try {
mStackSupervisor.startSpecificActivityLocked(next, true, false);
return true;
}
}
} else {
////應用進程沒有被建立
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
return true;
}
複製代碼
在上面的代碼中咱們能夠看到有一個判斷邏輯if (next.app != null && next.app.thread != null),這個是判斷應用程序進程是否被建立,從代碼中能夠看到,不管應用進程是否被建立,都會調用startSpecificActivityLocked()方法。這裏Activity的啓動又轉移到了ActivityStackSupervisor中。
除此以外,還有一個步驟是將mResumedActivity設置爲中止狀態,在咱們查看Activity的生命週期時,一個Activity啓動另一個Activity的時候,在調用過Activity的pause生命週期函數時纔會開始下一個Activity的生命週期。
/**ActivityStackSupervisor**/
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
//獲取應用進程信息
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
mService.mProcessStats);
}
//繼續啓動Activity
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
}
}
//建立應用進程
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
複製代碼
這裏就看到了若是應用進程不存在就會經過AMS建立應用進程,這裏再也不展開分析。若是應用進程存在就繼續啓動Activity。調用了realStartActivityLocked方法。
/**ActivityStackSupervisor**/
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException {
//......
// Create activity launch transaction.
//Android 9.0的啓動方式與其餘版本的不一樣,這裏換成了經過ClientTransaction的方式已啓動。
final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
r.appToken);
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, mService.isNextTransitionForward(),
profilerInfo));
// 這裏用來處理Activity生命週期回調
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
...
return true;
}
複製代碼
在上面能夠看到Android 9.0的啓動方式與其餘版本的不一樣,在Android 9.0裏主要經過回調的方式啓動Activity,最終會經過AMS中的ClientLifecycleManager.scheduleTransaction()方法調用ApplicationThread的scheduleTransaction(),最後的是執行的LaunchActivityItem的execute()方法。
/**TransactionExecutor**/
public void execute(ClientTransaction transaction) {
final IBinder token = transaction.getActivityToken();
//1.先執行CallBack
executeCallbacks(transaction);
//2.再執行Activity生命週期回調
executeLifecycleState(transaction);
mPendingActions.clear();
}
複製代碼
/**LaunchActivityItem**/
public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
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 */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
複製代碼
能夠看到這裏調用了ClientTransactionHandler的handleLaunchActivity()方法。從這裏Activity的啓動過程就從AMS中的調用切換到了ActivityThread中去了。
上面說到,Activity的啓動調用了ClientTransactionHandler的handleLaunchActivity()方法。咱們能夠發現ActivityThread是繼承自ClientTransactionHandler的。在ClientTransactionHandler中handleLaunchActivity是抽象方法,咱們直接在ActivityThread中看。
從這裏開始將開始執行Activity的生命週期函數。
/**ActivityThread**/
public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent) {
//......
//初始化WindowManagerService
WindowManagerGlobal.initialize();
final Activity a = performLaunchActivity(r, customIntent);
//......
return a;
}
複製代碼
能夠看到在這裏繼續調用了
/**ActivityThread**/
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//......
Activity activity = null;
try {
//獲取Activity實例
java.lang.ClassLoader cl = appContext.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) {
//......
}
try {
//初始化Application
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
//設置Context
appContext.setOuterContext(activity);
//調用Activity的attach()方法
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);
if (r.isPersistable()) {
//調用onCreate()生命週期函數
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.mInstrumentation(activity, r.state);
}
//......
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme); //設置主題
}
//......
r.activity = activity;
}
r.setState(ON_CREATE);
}
//......
return activity;
}
複製代碼
在上面的代碼能夠看到執行完Activity的attach()方法後,繼續執行Instrumentation的callActivityOnCreate()方法。
/**Instrumentation**/
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
複製代碼
這裏能夠看到,又執行了Activity的performCreate()方法。
/****/
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
//....
//調用onCreate()生命週期方法
if (persistentState != null) {
onCreate(icicle, persistentState);
} else {
onCreate(icicle);
}
}
複製代碼
在上面的代碼中調用了Activity的onCreate()生命週期方法。到這裏,在上面講到的TransactionExecutor的execute()方法中的回調已經執行完畢,接下來就是開始執行生命週期相關的回調。
咱們在分析上面代碼的時候知道,生命週期回調是一個ResumeActivityItem。
/**ResumeActivityItem**/
public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
"RESUME_ACTIVITY");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
複製代碼
能夠看到這裏有調用了handleResumeActivity()方法。
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, String reason) {
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
}
複製代碼
public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest, String reason) {
//執行Activity的performResume
r.activity.performResume(r.startsNotResumed, reason);
r.state = null;
r.persistentState = null;
r.setState(ON_RESUME);
} catch (Exception e) {
}
return r;
}
複製代碼
在上面的代碼中調用了Activity的performResume()方法。進而調用Activity的onResume()方法。這時Activity就呈現到了界面。Activity也算啓動完成。
上面以根Activity的視角分析了Activity的啓動過程。整個分析下來,感受到Activity的啓動仍是十分複雜的,可是在也並不須要面面俱到,可以把握大致,流程理解Android在啓動Activity的過程當中是怎麼調度的,這樣就達到了咱們的目的。