分析流程基於Android8.0原始碼
一般情況下我們通過Activity中的startActivity方法啟動一個Activity。這個流程中涉及一下幾個類:
android.app.Activity
android.app.Instrumentation
com.android.server.am.ActivityManagerService
com.android.server.am.ActivityStarter
com.android.server.am.ActivityStackSupervisor
android.app.ActivityThread
android.app.ActivityThread$ApplicationThread
複製程式碼
通過下圖瞭解一下各個類之間的呼叫關係
整個流程如上圖所示,多數程式碼直接跟著進就可以看到,這裡主要說一下兩次IPC,通過每個類的包名可以間接反映出整個啟動過程是一個C/S結構的跨程式操作。第一次跨程式是在Instumentation內部呼叫ActivityManagerService的startActivity方法時,程式碼如下:
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
複製程式碼
看一下ActivityManager:
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;
}
};
複製程式碼
這裡通過ServiceManager.getService(Context.ACTIVITY_SERVICE)返回一個IActivityManager,就是一個ActivityManagerService,IActivityManager在/frameworks/base/core/java/android/app/目錄下,是一個AIDL檔案,裡邊宣告瞭startActivity方法
interface IActivityManager {
...
int startActivity(...);
...
}
複製程式碼
ActivityManagerService繼承了IActivityManager.Stub,實現StartActivity方法。這個方法的呼叫是在系統程式,之後的邏輯在系統程式裡執行。
中間跟蹤的程式碼如圖,到ActivityStackSupervisor類中的realStartActivityLocked方法:
final boolean realStartActivityLocked(...) throws RemoteException {
...
app.thread.scheduleLaunchActivity();
...
}
複製程式碼
這裡app.thread是一個ApplicationThread物件,ApplicationThread是ActivityThread的一個內部類,看一下ApplicationThread的相關程式碼:
private class ApplicationThread extends IApplicationThread.Stub {
@Override
public final void scheduleLaunchActivity(...) {
...
}
複製程式碼
ApplicationThread繼承了IApplicationThread.Stub,這裡也是跨程式的一步,這個時候就從系統程式回到了應用自己的程式,然後通過反射獲取Activity例項,例項化Context,並呼叫獲取Activity例項的attach方法,傳入Context。最後呼叫到Activity的宣告週期的方法。
總結:應用內啟動Activity的邏輯主要經歷了兩次的跨程式過程,首先從應用自己程式跨程式到系統程式,處理Activity建立過程中的標誌位判斷,Activity所在的ActivityStack判斷、初始化,等等,最後跨程式會應用自己程式例項化Activity,並呼叫Activity的生命週期方法。