App啓動(一)Application的創建

大家都知道Java程序的入口是 main 方法,但在Android中我們只知道App啓動從Application開始,而Android是基於Java的,本身也是從main方法開始的,而這個 main方法是在ActivityThread類的。下面我們就看下ActivityThreadmain方法是如何工作的。

1. ActivityThread #main

public static void main(String[] args){
    ...
    //初始化Looper
    Looper.prepareMainLooper(); 
    ...
    //實例化一個ActivityThread
    ActivityThread thread = new ActivityThread();
    //這個方法最後就是爲了發送出創建Application的消息
    thread.attach(false);
    ... 
    Looper.loop();
    //主線程進入無限循環狀態,等待接收消息
}


很明顯這裏使用了Handler機制,先初始化Looper,然後實例化一個ActivityThread對象,而ActivityThread類有一個HHandler的子類)類型的變量mh,並進行了實例化,而後面則是調用Looper.loop()開啓了消息循環。

也就是說main方法所在的線程就是我們常說的主線程,我們繼續看main方法,可以看到創建ActivityThread的對象後,調用了attach方法,在這個方法裏進行了ApplicationActivity的相關創建。

2. ActivityThread #attach

public void attach(boolean system){
    ...
    //獲得IActivityManager實例,他是一個ActivityManagerProxy的示例
     final IActivityManager mgr = ActivityManager.getService();
    try {
        //這裏是關鍵。mAppThread是一個ApplicationThread實例,具體的在下面說
        mgr.attachApplication(mAppThread);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
    ...
}

首先我們拿到了一個IActivityManager的實例,它是通過ActivityManager.getService()獲取到的

我們看下ActivityManager.getService()相關的源碼

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;
        }
};

可以看到IActivityManager的實例是一個ActivityManagerService通過Binder機制得到的遠程對象,而ActivityManagerService即AMS是運行在系統進程,主要完成管理應用進程的生命週期以及進程的ActivityServiceBroadcastProvider等。

我們繼續回到attach方法,這裏調用了一行代碼mgr.attachApplication(mAppThread);,通過AMS的attachApplication方法將mAppThread對象關聯到了AMS。

而AMS通過調用mAppThread的相關方法進行Application的創建、生命週期的管理和Activity的創建、生命週期管理等,既然bindApplication對象如此重要,那麼我們來看下它到底是什麼

3.mAppThread是什麼?

mAppThreadActivityThread 的一個ApplicationThread類型的變量,而ApplicationThreadActivityThread 的一個內部類,大概代碼結構如下:

public final class ActivityThread {
	...
	final ApplicationThread mAppThread = new ApplicationThread();
	...
	private class ApplicationThread extends IApplicationThread.Stub {
        ...
    }
	public static void main(String[] args){
		...
	}
}

顯然ApplicationThread是一個BInder對象,可以通過Binder機制遠程訪問,這也就是爲什麼我們要將它傳遞給AMS的原因,AMS可以通過Binder機制調用它的的相關方法進行上面所說的Application的創建、聲明週期的管理等。

首先AMS通過遠程調用ApplicationThreadbindApplication方法進行Application對象的創建

4.ApplicationThread#bindApplication

public final void bindApplication(String processName, ApplicationInfo appInfo,
    List<ProviderInfo> providers, ComponentName instrumentationName,
    ProfilerInfo profilerInfo, Bundle instrumentationArgs,
    IInstrumentationWatcher instrumentationWatcher,
    IUiAutomationConnection instrumentationUiConnection, int debugMode,
    boolean enableBinderTracking, boolean trackAllocation,
    boolean isRestrictedBackupMode, boolean persistent, Configuration config,
    CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
    String buildSerial) {
    
    AppBindData data = new AppBindData();
    data.processName = processName;
    data.appInfo = appInfo;
    data.providers = providers;
    data.instrumentationName = instrumentationName;
    ...
    sendMessage(H.BIND_APPLICATION, data);
}
private void sendMessage(int what, Object obj) {
    sendMessage(what, obj, 0, 0, false);
}
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);
}

可以看到bindApplication方法通過Handler機制發送了H.BIND_APPLICATION消息將實現交給了H類進行處理

我們知道HandlerhandleMessage方法裏進行消息處理

public void handleMessage(Message msg) {
    switch (msg.what) {
            ...
            case BIND_APPLICATION:
                AppBindData data = (AppBindData)msg.obj;
                handleBindApplication(data);
                break;
            ...
    }
}

消息經過Hander處理後交給了ActivityThreadhandleBindApplication方法處理

5.ActivityThread #handleBindApplication

private void handleBindApplication(AppBindData data) {
    ...
    mInstrumentation = (Instrumentation)
        cl.loadClass(data.instrumentationName.getClassName())
        .newInstance();
    //通過反射初始化一個Instrumentation儀表。
    ...
    Application app;
    try {
         //通過LoadedApp的makeApplication創建Application實例
        app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;
   
        ...
        //讓Instrumentation儀表調用Application的onCreate()方法
        mInstrumentation.callApplicationOnCreate(app);
        ...
    }
    ...
}

通過上面源碼我們可以看到這裏使用data.info.makeApplication方法創建了Application對象

data.infoLoadedApk類型的對象,我們去這個類看它的makeApplication 方法

public Application makeApplication(boolean forceDefaultAppClass,
    Instrumentation instrumentation) {
    ...
    String appClass = mApplicationInfo.className;
    //獲取Application的類名。明顯是要用反射了。
    ...
    ContextImpl appContext = ContextImpl.createAppContext(mActivityThread
        , this);
    //留意下Context
    app = mActivityThread.mInstrumentation
        .newApplication( cl, appClass, appContext);
    //通過Instrumentation儀表創建Application
    ...
}

方法裏獲取了 Application 的類名,然後交給了 Instrumentation去創建對象,我們繼續看InstrumentationnewApplication方法

static public Application newApplication(Class<?> clazz
    , Context context) throws InstantiationException
    , IllegalAccessException
    , ClassNotFoundException {
    //反射創建,簡單粗暴
        Application app = (Application)clazz.newInstance();
        //關注下這裏,Application被創建後第一個調用的方法。
        //目的是爲了綁定Context。
        app.attach(context);
        return app;
}

Instrumentation直接用反射創建了Application 對象,然後調用了app.attach(context)方法綁定Context。這個方法裏調用了ApplicationattachBaseContext方法,這是我們應用端可以使用的最早的生命週期方法

final void attach(Context context) {
   //注意這個方法是一個可以比onCreate更早被調用的方法
   attachBaseContext(context);
   mLoadedApk = ContextImpl.getImpl(context).mPackageInf;
}

我們繼續回到handleBindApplication方法裏,通過LoadedAppmakeApplication創建Application實例後會調用mInstrumentation.callApplicationOnCreate(app)這行代碼執行ApplicationonCreate生命週期

public void callApplicationOnCreate(Application app) {
    app.onCreate();
}

可以看到只是簡單的調用了ApplicationonCreate方法,這是我們與Application打交道最多的方法。

至此Application對象已經創建出來了,並且我們已經走到了onCreate生命週期對象。Application的創建就分析到這裏了。

方法調用流程圖

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章