最近大致分析了一把 Activity 啟動的流程,趁著今晚剛?完精神狀態好,把之前記錄的寫成文章。
開門見山,我們直接點進去看 Activity 的 startActivity
, 最終,我們都會走到 startActivityForResult
這個方法,我們可以發現關鍵的程式碼:
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);
複製程式碼
我們會發現 Activity 啟動其實都經過了一箇中轉站叫做 Instrumentation
, 檢視Instrumentation
的 execStartActivity
方法:
/// 刪除了我們不關心的部分
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.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);
}
複製程式碼
我們會發現這裡通過 ActivityManager.getService
在進行通訊,進去檢視,我們發現這個 service 其實是一個 IActivityManager.aidl
, 說明這裡我們進行了一次 Android 的 IPC。
全域性搜尋 extends IActivityManager
我們可以發現進行通訊的就是 ActivityManagerService
, 檢視 startActivity
最終可以走到 ActivityStart
的 startActivityMayWait
方法。我們抽取它的關鍵程式碼:
這部分我們可以看到根據 intent 解析除了需要的資訊,並根據資訊去獲取了跳轉 Activity 的系統許可權。
這一部分程式碼,則對 intent 進行了處理和判斷,我們基本可以省略這部分非關鍵邏輯
最終我們會走到 startActivityLocked
方法,並走到 startActivity
這裡我們會看到很多對於不同的 ActivityManager
的 狀態進行邏輯判斷和處理,這裡不影響我們的關鍵流程,我們可以繼續往下分析, 分析 doPendingActivityLaunchesLocked
方法
startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
null, null /*outRecords*/);
複製程式碼
最終還是會走到另一個過載的 startActivity
:
mService.mWindowManager.deferSurfaceLayout();
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
複製程式碼
檢視 startActivityUnchecked
: 這裡程式碼邏輯比較長,我們檢視 ActivityStackSupervisor
的.resumeFocusedStackTopActivityLocked
方法
繼續檢視 resumeTopActivityUncheckedLocked
方法, 跟蹤到 resumeTopActivityInnerLocked
方法:
這邊我們檢視需要 restart 這個 Activity 的簡單情況,會呼叫 ActivityStackSupervisor
的 startSpecificActivityLocked
方法
這裡我們找到了邏輯的關鍵:如果 app的執行緒和程式都存在,我們會執行 realStartActivityLocked
方法。否則,會繼續進行 IPC 通知 ActivityManagerService
去執行 startProcessLocked
這裡我們差不多能猜到啟動邏輯:
- 如果啟動的是我們自己 app 程式的 Activity, 那麼直接去啟動就好了
- 如果我們啟動的 Activity 所在的程式不存在,例如:我們把微信 kill 了,然後跳轉微信分享的 Activity,或者我們點選launch 的微信圖示,那麼,我麼就會走建立新程式的邏輯
那麼我們分別來跟蹤這2種情況:
啟動自己的Activity
我們可以找到這段程式碼的關鍵邏輯,我們先分析下 app.thread
是什麼。跟蹤進去會發現是一個 IApplicationThread
, 可以發現這裡又是一個 aidl, 最後我們可以找到 ApplicationThread
,
private class ApplicationThread extends IApplicationThread.Stub
複製程式碼
這是 ActivityThread
的一個靜態內部類,ActivtyThread和啟動Activity 相關,那麼這個類就應該是和 Application 啟動相關。
我們會發現最後其實發了一個message 到訊息佇列中,找到 H
這個 handler 的 handleMessage
方法
case LAUNCH_ACTIVITY: {
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
} break;
複製程式碼
檢視 handleLaunchActivity
方法
Activity a = performLaunchActivity(r, customIntent);
複製程式碼
在performLaunchActivity
方法中可以看到
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
複製程式碼
這裡,我們發現這裡通過 Insteumentation
new 了一個 Activity
通過以上程式碼,我們還可以發現 new 出 Activity 後的幾個步驟
- attach Activity, 目測會有初始化 window 的流程
- 設定 theme
- Activity 的
onCreate
流程 - Activity 如果已經銷燬,會去執行
onRestoreInstance
,我們可以在這裡做資料恢復的操作 - Activity 在
onCreate
完成後的一些操作
到這裡,我們的 Activity 就啟動成功了
啟動新的程式
下面來分析我們的第二種情況,我們可以跟蹤到 ActivityManagerService
的 `startProcessLocked 方法, 這個方法最終會走到自己的過載方法:
如果我們啟動的是一個 webview service, 則會走到 startWebView
,這裡我們不考慮,所以我們分析的是 Process.start
這種初始化一個普通程式的情況。
這個方法最後呼叫了 ZygoteProcess
的 start
方法
這裡我們也可以大致分析出來,這裡就是在通過 socket 通訊請求 Zygote
程式 fork 一個子程式,作為新的 APP 程式,具體流程本篇文章暫時不做深究。
最終我們會啟動 ActivityThread
的 main
方法,繼續走到 attach
方法
這裡我們能看到啟動主執行緒的 Looper, 建立系統 Context 等工作,最終我們走到 ApplicationThread
的 bindApplication
, 程式碼這裡就不貼了,這裡負責了 Application 在初始化的時候的各種工作。包括 LoadedAPK
的 makeApplication
過程。
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
複製程式碼
這裡會發現,正常模式下,我們走到了 ActivityStackSupervisor
的 attachApplicationLocked
方法,後面就又會和第一部分介紹的一樣,走到 realStartActivityLocked
方法,去建立並執行 Activity 的生命週期。
總結
到這裡,Activity 的啟動流程就大致梳理出來了。基本就是,Instrumentation
負責 Activity 的建立和中轉, ActivityStackSupervisor
負責 Activity的 棧管理。Activity 都通過了 ActviityServerManager
來進行管理。
大概的關係如下圖所示:
後續
這裡我只是對Activity的啟動流程做了一個簡單的梳理。我們會發現每個模組和細節都有幾百幾百行的程式碼。非常的複雜。下面的內容有興趣大家也可以細細探究。
- 存在的 Activity 是怎麼管理的,怎麼走 onResume 去恢復的
- Activity 不同的 launch mode是怎麼處理的
- zygote fork 新的app程式的細節
- LoadedApk 是怎麼載入 apk 的內容的
- Activity 初始化完成後,內部是 window 又是怎麼初始化並且渲染上 UI 內容的