Android原始碼分析:Activity啟動流程

LeaY發表於2018-03-29

分析流程基於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
複製程式碼

通過下圖瞭解一下各個類之間的呼叫關係

Android原始碼分析:Activity啟動流程

整個流程如上圖所示,多數程式碼直接跟著進就可以看到,這裡主要說一下兩次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的生命週期方法。

相關文章