1. 前言
由于系統極強的封裝特性,我們在啟動 Activity 時并不知道系統內部都是如何完成整個的啟動流程的?如何創建一個 Activity 對象?什么時候調用 onCreate() 方法的?
本文中所有源碼都是基于 Android API 29。
2. Activity 的啟動方式
Activity 的啟動可以通過 startActivity()
或者 startActivityForResult()
,兩者的區別在于是否要接收來自被啟動 Activity 的返回結果。
Intent intent = new Intent(activity, CaptureActivity.class);
activity.startActivity(intent); //不接收來自 CaptureActivity 的返回結果
Intent intent = new Intent(activity, CaptureActivity.class); //接收來自 CaptureActivity 的返回結果
activity.startActivityForResult(intent, REQUEST_CAPTURE);
3. 源碼解析
3.1 啟動 Activity
無論我們是通過 startActivity() 各種重載的方法還是通過 startActivityForResult() 方法啟動 Activity,最后都會調用 Activity 的 startActivityForResult(Intent intent, int requestCode, Bundle options)。Context 是一個抽象類,有抽象方法 startActivity,ContextWrapper 繼承自 Context ,是 Context 的代理類,實現了 startActivity;Activity 繼承自 ContextWrapperTheme,ContextWrapperTheme 繼承自 ContextWrapper,所以最終在 Activity 中實現的 startActivity 實際上是抽象類 Context 中的 startActivity 方法。
-
startActivityForResult()
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);
}
}
}
1)mParent,是一個 Activity 對象,表示當前 Activity 的父 Activity,判斷 mParent 是否為空,為空直接執行步驟4,不為空執行2,3;
2)mInstrumentation.execStartActivity,調用了 Instrumentation 的 execStartActivity 方法;
3)mMainThread.sendActivityResult,如果步驟2中返回結果不為空,調用ActivityThread 的 sendActivityResult 方法;
4)mParent 為空,調用父 Activity 的 startActivityFromChild 方法;
先來看看步驟2中 Instrumentation 的 execStartActivity 方法,在這里利用了 Binder 機制,跨進程調用了 ATMS(ActivityTaskManagerService)的 startActivity 方法,ATMS 運行在系統服務進程中。
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityTaskManager.getService()
.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;
}
1)ActivityTaskManager.getService().startActivity 即是調用了 ATMS 的 startActivity 方法;
2)checkStartActivityResult(),檢查啟動 Activity 的結果。
先來看 checkStartActivityResult 方法,主要是檢查啟動 Activity 的結果,有異常則拋出。例如下面代碼中是一個典型的未找到啟動 Activity 的異常,因為我們沒有在 AndroidManifest 文件中聲明我們的 Activity。
public static void checkStartActivityResult(int res, Object intent) {
if (!ActivityManager.isStartResultFatalError(res)) {
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);
...
}
}
接著來看 ActivityTaskManager 的 getService 方法:
-
ActivityTaskManager
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};
這里是通過 Singleton 返回了一個 IActivityTaskManager 對象,Singleton 是一個單例的封裝類,第一次調用它的get 方法時它會通過 create 方法來初始化一個 IActivityTaskManager,IActivityTaskManager 其實是一個 Binder 對象,負責應用和 ActivityTaskManagerService (以下簡稱 ATMS)直接的通信。
ATMS 運行在服務進程(system_server)中,Instrumentation 實現了應用和 ATMS 之間的通信,Activity 的啟動就轉移到了 ATMS 中:
-
ActivityTaskManagerService
ATMS 中 startActivity 方法調用了 startActivityAsUser 方法,startActivityAsUser 調用了 ActivityStarter 的 execute 方法。
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) {
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
.execute();
}
getActivityStartController() 獲取到 ActivityStarController 對象,調用 ActivityStarController 的 obtainStarter() 獲取 ActivityStarter 對象,ActivityStart 設置一些需要傳給應用進程的信息,然后調用了 ececute 方法。
-
ActivityStarter
execute 方法根據啟動請求調用 startActivityMayWait 方法或者 startActivity 方法,直接來看 startActivity 方法,startActivity 方法調用了 startActivityUnchecked 方法,startActivityUnchecked 調用了 ActivityTask 的 sendActivityResultLocked 方法。
//ActivityStarter
int execute() {
try {
if (mRequest.mayWait) {
return startActivityMayWait(...);
} else {
return startActivity(...);
}
} finally {
onExecutionComplete();
}
}
private ActivityStack mTargetStack;
//ActivityStarter#startActivityUnchecked()
mTargetStack.startActivityResultLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
mOptions);
-
ActivityTask
sendActivityResultLocked 方法通過 ActivityTaskManagerService 調用了 ClientLifecycleManager
的 scheduleTransaction 方法
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
if (!(client instanceof Binder)) {
transaction.recycle();
}
}
scheduleTransaction 方法通過 ClientTransaction 的 schedule 方法調用了 IApplicationThread
的 scheduleTransaction 方法。
private IApplicationThread mClient;
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
-
IApplicationThread 和 ApplicationThread
IApplicationThread 繼承了 IInterface 接口,它是一個 Binder 類型的接口,IApplicationThread 的最終實現類是 ActivityThread 的內部類 ApplicationThread
。ApplicationThread 繼承自 ApplicationThreadNative
,ApplicationThreadNative 繼承自 Binder 并實現來 IApplicationThread 接口。ApplicationThreadNative 的作用和使用 AIDL 時系統生成的類是一樣,它的內部有一個 ApplicationThreadProxy 類,這個類也就是 AIDL 文件的代理類。綜上所述,IApplicationThread 的實現類就是 ApplicationThreadNative,而 ApplicationThreadNative 被定義為了抽象類,那最終實現者就是 ApplicationThread。
-
ActivityThread
ApplicationThread 的 scheduleTransaction 方法調用了 ActivityThread 的 scheduleTransaction 方法,ActivityThread 繼承自 ClientTransactionHandler
,ClientTransactionHandler 是抽象類,它的 scheduleTransaction 方法中調用 sendMessage 方法發送了一條 EXECUTE_TRANSACTION 類型的消息,sendMessage 是抽象方法,ActivityThread 實現了該方法,ActivityThread 的 sendMessage
方法中將要發送的消息封裝在 Message 中,通過 ActivityThread 的 H
對象 mH 執行了消息的發送,H 是 ActivityThread 的靜態內部類,繼承自 Handler,用于接收并處理來自其他線程的消息。
//ClientTransactionHandler
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
abstract void sendMessage(int what, Object obj);
//ActivityThread
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
...
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
ActivityThread 中,H
收到 EXECUTE_TRANSACTION 類型的消息,調用 TransactionExecutor
的 execute 方法,execute 方法調用了 executeCallbacks 方法,executeCallbacks 中調用 LaunchActivityItem
的 execute 方法,LaunchActivityItem 繼承自 ClientTransactionItem 并實現了 execute 方法,execute 方法調用了 ClientTransactionHandler
的 handleLaunchActivity 方法,ActivityThread 繼承自 ClientTransactionHandler ,并實現了 handleLaunchActivity 方法,這里又回到了 ActivityThread
中的 handleLaunchActivity 方法內,handleLaunchActivity 方法調用了 performLaunchActivity 方法。
-
performLaunchActivity 方法:
1)從 ActivityClientRecord
中獲取待啟動 Activity 的啟動信息;
2)調用 createBaseContextForActivity 方法創建 ContextImpl
對象,該方法中調用 ContextImpl 的 createActivityContext 方法創建 ContextImpl 對象;
ContextImpl appContext = createBaseContextForActivity(r);
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
...
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
...
return appContext;
}
3)調用 Instrumentation
的 newActivity 方法新建并加載 Activity,newActivity 方法中調用 AppComponentFactory 的 instantiateActivity方法,instantiateActivity 方法通過在 performLaunchActivity 方法中新建的 ClassLoader
加載新建的 Activity 類;
activity = mInstrumentation.newActivity(cl,component.getClassName(),r.intent);
//Instrumentation
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
String pkg = intent != null && intent.getComponent() != null
? intent.getComponent().getPackageName() : null;
return getFactory(pkg).instantiateActivity(cl, className, intent);
}
//AppComponentFactory
public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
@Nullable Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Activity) cl.loadClass(className).newInstance();
}
4)通過 LoadApk
的 makeApplication 方法創建一個 Application 對象;
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
//r.packageInfo 就是 ActivityClientRecord 中存的 LoadApk 對象
5)調用 Activity 的 attach
方法,ContextImpl 通過 Activity 的 attach 方法來和 Activity 建立關聯,除此之外,attach 方法還完成了 Window 的創建并建立自己和 Window 的關聯,這樣當 Window 接收到外部輸入事件后就可以將事件傳遞給 Activity;
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,
r.assistToken);
//Activity的attatch
//將創建的 Activity 和 ContextImpl
attachBaseContext(context); 建立關聯
//為新建的 Activity 創建 Window,用于接收到外部輸入事件后將事件傳給Activity
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
6)調用 Instrumentation
的 callActivityOnCreate 方法,callActivityOnCreate 方法調用 Activity
的 performCreate 方法,performCreate 調用 onCreate
方法。
mInstrumentation.callActivityOnCreate(activity, r.state);
//Instrumentation
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
//Activity
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
...
if (persistentState != null) {
onCreate(icicle, persistentState);
} else {
onCreate(icicle);
}
...
}
至此走完了從發起啟動 Activity 的請求、Activity 的創建、Activity 的加載到最后調用 onCreate 方法的整個流程。這里只是分析整個的流程大概,涉及到啟動模式等的細節沒有去探討。
4. 總結
4.1 重要類
- Instrumentation:管理應用進程和系統進程之間的通信;
- ActivityTaskManager:實現應用進程和運行在系統進程的 ActivityTaskManagerService 的通信;
- ActivityTaskManagerService:負責管理activity;
- ActivityStarter:負責啟動模式,啟動Flag相關處理;
- ActivityStack:負責管理單獨棧的 Activity 和其狀態,即具體啟動的執行等;
- ApplicationThread(IApplicationThread):繼承自 IApplicationThread,會在 ActivityTask 中調用,處理 Activity、Service、Broadcast 的創建等操作;
- ActivityThread(ClientTransactionHandler):繼承自 ClientTransactionHandler,管理應用進程中主線程,執行和調度 Activity、廣播,處理來自 Activity 的任務請求;
- ActivityClientRecord:保存和 Activity 相關的參數信息,還保存了和 Activity 關聯的 Window 的信息;
4.2 完整流程圖
5. 參考
- Activity 啟動流程分析
- 深入研究源碼:Activity 啟動流程分析
- 《Android 開發藝術探索》