Activity 啟動流程
Activity 啟動呼叫流程 (基於5.0原始碼)
我們從 startActivity 開始:
startActivity()
startActivity()方法有多個過載,但是都會呼叫到 startActivityResult:
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
... //
}
...// 省略大量程式碼
}
Ok,我們可以看到 呼叫到了 Instrumentation 的 execStartActivity 方法。
下面我們看一下 execStartActivity
中的兩行重點程式碼:
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);
可以看到,呼叫到了 ActivityManagerNative.getDefault() 的 startActivity。 而getDefault()返回的是一個 IActivityManager.
checkStartActivityResult()是校驗activity 的啟動結果的,比如我們沒有在androidManifest 註冊,等等。就會丟擲異常。
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;
}
};
可以看到是一個單例。IActivityManager 是一個 Binder 介面
public interface IActivityManager extends IInterface {
...// 方法
}
而該Binder 的真正實現 是 ActivityManagerService(簡稱 AMS) 。 所以接下來我們來看 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 options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
啥實事也沒幹,直接轉調了 startActivityAsUser
繼續跟進,
@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, userId, null, null);
}
該方法調了 ActivityStackSupervisor
的 startActivityMayWait
方法。 在該方法中又呼叫了自身的 startActivityLocked
方法,該方法中又呼叫到 startActivityUncheckedLocked() 又從該方法呼叫到了 ActivityStack 的 resumeTopActivityLocked
方法。這時 已經從 ActivityStackSupervisor 轉到了 ActivityStack
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
} finally {
inResumeTopActivity = false;
}
return result;
}
上面程式碼看到 resumeTopActivityLocked
呼叫了 resumeTopActivityInnerLocked
在該方法中:
mStackSupervisor.startSpecificActivityLocked(next, true, false);
又回到了 ActivityStackSupervisor
中, ok, startSpecificActivityLocked
中 呼叫了 realStartActivityLocked
看到這個名字,說明我們已經差不多了。 該方法的關鍵程式碼如下:
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState,
results, newIntents, !andResume, mService.isNextTransitionForward(),
profilerInfo);
那麼app.thread 是什麼呢?? 它是 IApplicationThread
型別。
public interface IApplicationThread extends IInterface {}
是一個Binder 介面。 AMS程序通過該 binder介面 來呼叫 app程序的方法。
IApplicationThread
的實現 是在 ActivityThread 中的 ApplicationThread
, IApplicationThread 中定義了很多介面方法。都是和四大元件相關的
void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,
int configChanges, boolean dontReport) throws RemoteException;
void scheduleStopActivity(IBinder token, boolean showWindow,
int configChanges) throws RemoteException;
void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;
void scheduleResumeActivity(IBinder token, int procState, boolean isForward, Bundle resumeArgs)
throws RemoteException;
void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
IVoiceInteractor voiceInteractor, int procState, Bundle state,
PersistableBundle persistentState, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
ProfilerInfo profilerInfo) throws RemoteException;
void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, int configChanges,
boolean notResumed, Configuration config) throws RemoteException;
void scheduleNewIntent(List<Intent> intent, IBinder token) throws RemoteException;
......
ok 我們來看 ApplicationThread
的實現.
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
IVoiceInteractor voiceInteractor, int procState, Bundle state,
PersistableBundle persistentState, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
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;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
scheduleLaunchActivity
中儲存了啟動Activity的相關資訊,然後 傳送了一個訊息 H.LAUNCH_ACTIVITY
這裡呢,我們就需要提一下這個 H .
final H mH = new H();
H 繼承自Handler。負責系統訊息的處理。 訊息的處理是在 handleMessage
方法中。 至於這裡為什麼要使用Handler 。 因為之前的操作 都是在服務端的 Binder 執行緒池中,所以我們這裡需要切換到主執行緒。 handleMessage中的 呼叫了 handleLaunchActivity
方法。 而該方法 又呼叫了 performLaunchActivity
方法.
該方法中做了如下幾件事:
1.從ActivityClientRecord 中取出 待啟動的Activity 的元件資訊。
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
2.通過Instrumentation 的 newActivity 方法 使用類載入器建立 Activity 物件
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);
}
}
3.通過LoadedApk 的 makeApplication 方法來嘗試建立 Application物件。
4.建立ContextImpl 物件並通過Activity 的 attach 方法來完成一些重要資料的初始化
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.voiceInteractor);
ContextImpl 是context 的具體實現,Context 中的大部分邏輯都是由 ContextImpl 來實現的。 ContextImpl 是通過 Activity 的 attach 方法 來和 Activity 建立關聯的。 而且 attach 方法中 還會完成 Window 的建立 並建立和 Winwod 的關聯。 這樣當Window 接收到外部輸入事件後就可以傳遞給Activity 了。
5.呼叫Activity 的 OnCreate 方法。
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
整體總結:
當啟動一個Activity時,會通過 Instrumentation 類來 execStartActivity來啟動,該類 可以看作是一個管家。裡面有很多 關於 Activity 生命週期的方法,可以看作是一箇中間件。 在該方法中會 呼叫 IActivityManager 中的 startActivity 。該介面是個Binder介面,真正的實現是 服務端的 AMS, 在ams 中會 涉及到兩個類 ActivityStackSupervisor 和 ActivityStack 處理 Activity 相關的啟動邏輯。 當準備好後, 會呼叫 app.thread.scheduleLaunchActivity(). app.thread 的型別是 IApplicationThread 介面,是個Binder 介面。真正的實現類是 ApplicationThread 。 在 scheduleLaunchActivity
中進行了資料的儲存,然後傳送 LAUNCH_ACTIVITY 的訊息,由 H 。 H 繼承自Handler。 此處由於AMS 端的呼叫是在 binder 執行緒池,所以要切換到主執行緒。 在 handleMessage 中進行了相關的 Activity的建立、初始化、以及 OnCreate 的呼叫。
簡記:
Handler 在Android 中執行緒通訊起著很大的作用, Framework 層有很多的Handler,執行在不同的執行緒; 而我們應用層也有一個比較重要的Handler,即 ActivityThread
中的 mH. 執行在 ui 執行緒。
ApplicationThread
為 IApplicationThread 的具體實現類, 用來接收服務端的訊息, 四大元件就是通過 ApplicationThread
來接收服務端的訊息的。
ActivityStarter 處理一些 intent 和 flag 。 然後交給ActivityStackSupervisor 和 ActivityStack 來處理被呼叫Activity 的程序進棧。 如果被呼叫者的程序存在,就會使用 ApplicationThread 這個客戶端的 Binder 通知已存在的呼叫者程序啟動Activity, 如果不存在,就會使用 Socket 通知 Zygote 程序 fork 出一個程序,用來承載即將啟動的Activity。
ActivityStarter : intent 和 flag 如何開啟Activity
ActivityStack: 管理Activity
ActivityStack 管理Activity的方法:
startActivityLocked()
resumeTopActivityLocked()
completeResumeLocked()
startPausingLocked()
completePauseLocked()
stopActivityLocked()
activityPausedLocked()
finishActivityLocked()
activityDestroyedLocked()