Android Activity啟動(dòng)過程-從桌面點(diǎn)擊圖標(biāo)到調(diào)用Activity的OnCreate

1、概述

當(dāng)用戶從桌面點(diǎn)擊一個(gè)應(yīng)用圖標(biāo)時(shí),該應(yīng)用就會(huì)啟動(dòng)并顯示主Activity,即在AndroidManifest中標(biāo)注如下過濾器的Activity:

image

里面的category中涉及到LAUNCHER。這個(gè)其實(shí)和Laucher進(jìn)程有關(guān),這是一個(gè)桌面進(jìn)程。所以從桌面點(diǎn)擊圖標(biāo)到應(yīng)用啟動(dòng)顯示的頁(yè)面的過程,其實(shí)就是從一個(gè)應(yīng)用啟動(dòng)到另一個(gè)應(yīng)用的過程。

總體流程大致如下圖所示:

image

① 點(diǎn)擊桌面App圖標(biāo),Launcher進(jìn)程采用Binder IPC向system_server進(jìn)程發(fā)起startActivity請(qǐng)求。

② system_server進(jìn)程接收到請(qǐng)求后,向zygote進(jìn)程發(fā)送創(chuàng)建進(jìn)程的請(qǐng)求。

③ Zygote進(jìn)程fork出新的子進(jìn)程,即App進(jìn)程。

④ App進(jìn)程,通過Binder IPC向sytem_server進(jìn)程發(fā)起attachApplication請(qǐng)求。

⑤ system_server進(jìn)程在收到請(qǐng)求后,進(jìn)行一系列準(zhǔn)備工作后,再通過binder IPC向App進(jìn)程發(fā)送scheduleLaunchActivity請(qǐng)求。

⑥ App進(jìn)程的binder線程(ApplicationThread)在收到請(qǐng)求后,通過handler向主線程發(fā)送LAUNCH_ACTIVITY消息。

⑦ 主線程在收到Message后,通過發(fā)射機(jī)制創(chuàng)建目標(biāo)Activity,并回調(diào)Activity.onCreate()等方法。

⑧ 到此,App便正式啟動(dòng),開始進(jìn)入Activity生命周期,執(zhí)行完onCreate/onStart/onResume方法,UI渲染結(jié)束后便可以看到App的主界面。

2、概念介紹

2.1 Launcher

如開頭所說Launcher本質(zhì)上也是一個(gè)應(yīng)用程序,和我們的App一樣,同時(shí)桌面顯示的頁(yè)面也是一個(gè)Activity:


//packages/apps/Launcher2/src/com/android/launcher2/Launcher.java

public final class Launcher extends Activity

        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,

                  View.OnTouchListener {

                  }

Launcher這個(gè)Activity實(shí)現(xiàn)了點(diǎn)擊、長(zhǎng)按等回調(diào)接口,來接收用戶的輸入。既然是Activity,那么從Launcher的Activity跳轉(zhuǎn)到我們應(yīng)用的主Activity,和我們平時(shí)從一個(gè)Activity跳轉(zhuǎn)到另一個(gè)Activity的其實(shí)從代碼角度一樣。即捕捉圖標(biāo)點(diǎn)擊事件,然后startActivity()發(fā)送對(duì)應(yīng)的Intent請(qǐng)求。

2.2 system_server

startActivity()發(fā)送過來的請(qǐng)求其實(shí)是發(fā)送給system_server。而SystemServer也是一個(gè)進(jìn)程。所以這一過程其實(shí)涉及到了進(jìn)程間的通信,這邊的這一過程是采用Binder的方式來進(jìn)行的。system_server這個(gè)進(jìn)程是Android Framework層里面非常重要的一個(gè)進(jìn)程。系統(tǒng)里面重要的服務(wù)都是在這個(gè)進(jìn)程里面開啟的,比如 ActivityManagerService、PackageManagerService、WindowManagerService等等。

而今天重點(diǎn)要涉及到ActivityManagerService這個(gè)服務(wù),其簡(jiǎn)稱AMS。ActivityManagerService進(jìn)行初始化的時(shí)機(jī)很明確,就是在SystemServer進(jìn)程開啟的時(shí)候,就會(huì)初始化ActivityManagerService。

我們的App通過調(diào)用startActivity()并不能直接打開另外一個(gè)App,這個(gè)方法會(huì)通過一系列的調(diào)用,最后告訴AMS說:“我要打開這個(gè)App,我知道他的住址和名字,你幫我打開吧!”所以是AMS來通知zygote進(jìn)程來fork一個(gè)新進(jìn)程,來開啟我們的目標(biāo)App。

除此之外,其實(shí)所有的Activity的開啟、暫停、關(guān)閉都需要AMS來控制,所以我們說,AMS負(fù)責(zé)系統(tǒng)中所有Activity的生命周期。

在Android系統(tǒng)中,任何一個(gè)Activity的啟動(dòng)都是由AMS和應(yīng)用程序進(jìn)程相互配合來完成的。AMS服務(wù)統(tǒng)一調(diào)度系統(tǒng)中所有進(jìn)程的Activity啟動(dòng),而每個(gè)Activity的啟動(dòng)過程則由其所屬的進(jìn)程具體來完成。

2.3 zygote

如上所說,ActivityManagerService收到一個(gè)打開一個(gè)應(yīng)用程序的通知后會(huì)發(fā)送創(chuàng)建進(jìn)程的請(qǐng)求給到zygote來創(chuàng)建一個(gè)app進(jìn)程。

在Android系統(tǒng)里面,zygote是一個(gè)進(jìn)程的名字。Android是基于Linux System的,當(dāng)你的手機(jī)開機(jī)的時(shí)候,Linux的內(nèi)核加載完成之后就會(huì)啟動(dòng)一個(gè)叫“init“的進(jìn)程。在Linux System里面,所有的進(jìn)程都是由init進(jìn)程fork出來的,我們的zygote進(jìn)程也不例外。

我們都知道,每一個(gè)App其實(shí)都是一個(gè)單獨(dú)的dalvik虛擬機(jī)并對(duì)應(yīng)一個(gè)單獨(dú)的進(jìn)程。所以當(dāng)系統(tǒng)里面的第一個(gè)zygote進(jìn)程運(yùn)行之后,在這之后再開啟App,就相當(dāng)于開啟一個(gè)新的進(jìn)程。而為了實(shí)現(xiàn)資源共用和更快的啟動(dòng)速度,Android系統(tǒng)開啟新進(jìn)程的方式,是通過fork第一個(gè)zygote進(jìn)程實(shí)現(xiàn)的。所以說,除了第一個(gè)zygote進(jìn)程,其他應(yīng)用所在的進(jìn)程都是zygote的子進(jìn)程。而zygote的直白翻譯為“受精卵”,也是很形象生動(dòng)了。

而創(chuàng)建的新進(jìn)程的入口就是ActivityThread.main()方法,之后的部分將著重介紹。

3、應(yīng)用創(chuàng)建到顯示

3.1 啟動(dòng)應(yīng)用程序

Android中,一個(gè)應(yīng)用程序的開始可以說就是從ActivityThread.java中的main()方法開始的。下面是main()比較關(guān)鍵的代碼:


public static void main(String[] args){

    ...

    Looper.prepareMainLooper();

    //初始化Looper

    ...

    ActivityThread thread = new ActivityThread();

    //實(shí)例化一個(gè)ActivityThread

    thread.attach(false);

    //這個(gè)方法最后就是為了發(fā)送出創(chuàng)建Application的消息

    ...

    Looper.loop();

    //主線程進(jìn)入無(wú)限循環(huán)狀態(tài),等待接收消息

}

從源碼中可以看到,main()方法中主要做的事情是,初始化主線程的Looper、主Handler。并使主線程進(jìn)入等待接收Message消息的無(wú)限循環(huán)狀態(tài)。并在進(jìn)入等待接收消息前實(shí)例化一個(gè)實(shí)例化一個(gè)ActivityThread,并調(diào)用其attach()方法。從這也可以想象到為什么說Android的設(shè)計(jì)是一個(gè)事件驅(qū)動(dòng)的模型了。

3.2 應(yīng)用程序和AMS關(guān)聯(lián)

我們?cè)诳匆幌聇hread.attach(false)中的關(guān)鍵代碼:


public void attach(boolean system){

    ...

    final IActivityManager mgr = ActivityManagerNative.getDefault(); 

    //獲得IActivityManager實(shí)例

    try {

        mgr.attachApplication(mAppThread);

    } catch (RemoteException ex) {

        throw ex.rethrowFromSystemServer();

    }

    ...

}

里面的IActivityManager 是一個(gè)接口,當(dāng)我們調(diào)用ActivityManagerNative.getDefault()獲得的實(shí)際是一個(gè)代理類的實(shí)例——ActivityManagerProxy,這個(gè)東西實(shí)現(xiàn)了IActivityManager接口。打開源碼你會(huì)發(fā)現(xiàn),ActivityManagerProxy是ActivityManagerNative的一個(gè)內(nèi)部類。既然是一個(gè)代理類它必定有代理的對(duì)象。查看一下ActivityManagerProxy的構(gòu)造函數(shù):


public ActivityManagerProxy(IBinder remote) {

        mRemote = remote;

}

這個(gè)構(gòu)造函數(shù)非常的簡(jiǎn)單。首先它需要一個(gè)IBinder參數(shù),然后賦值給mRemote變量。這個(gè)mRemote顯然是ActivityManagerNative的成員變量。但對(duì)它的操作是由ActivityManagerProxy來代理間接進(jìn)行的。這樣設(shè)計(jì)的好處是保護(hù)了mRemote,并且能夠在操作mRemote前執(zhí)行一些別的事務(wù),并且我們是以IActivityManager的身份來進(jìn)行這些操作。

該構(gòu)造函數(shù)的調(diào)用地點(diǎn):


static public IActivityManager asInterface(IBinder obj) {

    if (obj == null) {

        return null;

    }

    IActivityManager in =

        (IActivityManager)obj.queryLocalInterface(descriptor);

    //先檢查一下有沒有

    if (in != null) {

        return in;

    }

    ...

    return new ActivityManagerProxy(obj);

    //這個(gè)地方調(diào)用了構(gòu)造函數(shù)

}

上面這個(gè)方法是ActivityManagerNative中的一個(gè)靜態(tài)方法,它會(huì)調(diào)用到ActivityManagerProxy的構(gòu)造方法。這個(gè)靜態(tài)方法也需要一個(gè)IBinder作為參數(shù)。

查找這個(gè)函數(shù)的調(diào)用地點(diǎn)以及傳入的參數(shù)到底是什么:


private static final SingletongDefault = new Singleton() {

    protected IActivityManager create() {

      IBinder b = ServiceManager.getService("activity");

      //重點(diǎn)啊!IBinder實(shí)例就是在這里獲得的。

        ...

        IActivityManager am = asInterface(b);

        //調(diào)用了上面的方法。

        ...

        return am;

    }

};

這是ActivityManagerNative的靜態(tài)常量,它是一個(gè)單例。在其中終于獲得了前面一直在用的IBinder實(shí)例。


IBinder b = ServiceManager.getService("activity");

到這里應(yīng)該已經(jīng)非常清晰了,IActivityManager 獲取到的就是一個(gè)ActivityManagerService的代理。有了這個(gè)代理之后就可以作為客戶端通過Binder機(jī)制將app作為客戶端,ActivityManagerService作為服務(wù)端來進(jìn)行通信了。具體Binder進(jìn)程間通信機(jī)制請(qǐng)看我之前一篇文章:Binder進(jìn)程間通信機(jī)制

我們回到前面的thread.attach(false)方法中,接著往下看在獲得IActivityManager實(shí)例之后,將會(huì)執(zhí)行它的attachApplication(mAppThread)方法。該方法會(huì)傳入一個(gè)mAppThread參數(shù)。在ActivityThread這個(gè)類的成員變量中,有這么一行代碼:


final ApplicationThread mAppThread = new ApplicationThread();

ApplicationThread是作為ActivityThread中的一個(gè)常量出現(xiàn)的。這表明系統(tǒng)不希望這個(gè)變量中途被修改,也說明其的重要性。ApplicationThread類繼承自ApplicationThreadNative。并且ApplicationThread是ActivityThread的一個(gè)內(nèi)部類。從設(shè)計(jì)角度可以看出,該類是專門讓ActivityThread來使用的一個(gè)類。

看一下ApplicationThread的父類ApplicationThreadNative:


public abstract class ApplicationThreadNative extends Binder

    implements IApplicationThread{

...

}

我們從ApplicationThreadNative看到它也是一個(gè)Binder,同時(shí)實(shí)現(xiàn)了IApplicationThread接口。這個(gè)Binder并不是Binder代理,這個(gè)Binder說明了應(yīng)用程序在作為客戶端的同時(shí),也作為了服務(wù)端。而作為服務(wù)端的Binder就是ApplicationThread。而 mgr.attachApplication(mAppThread) 這行代碼就是通過mgr將ApplicationThread的信息作為數(shù)據(jù)發(fā)送給AMS,方便日后AMS通過ApplicationThread的代理發(fā)送數(shù)據(jù)給ApplicationThread來達(dá)到控制app的Activity生命周期等一系列操作。

幾經(jīng)輾轉(zhuǎn),ApplicationThread的信息終于傳遞到了AMS中,我們可以從AMS的源碼中找到這個(gè)函數(shù):


private final boolean attachApplicationLocked(IApplicationThread thread

, int pid) {

    ...

    thread.bindApplication();

    ...

}

3.3 創(chuàng)建Application

ApplicationThread以IApplicationThread的身份到了ActivityManagerService中(其實(shí)在ActivityManagerService中的是ApplicationThread的代理),經(jīng)過一系列的操作,最終被調(diào)用了自己的bindApplication()方法,發(fā)出初始化Applicationd的消息:


public final void bindApplication(String processName, ApplicationInfo appInfo, Listproviders, 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){

    ...

    sendMessage(H.BIND_APPLICATION, data);

}

bindApplication()函數(shù)就是AMS的ApplicationThread的代理,通過Binder進(jìn)程間通信調(diào)用app進(jìn)程的ApplicationThread的bindApplication()方法。該方法里面有一句關(guān)鍵代碼


sendMessage(H.BIND_APPLICATION, data);

還記不記得最開始main函數(shù)創(chuàng)建的Looper。而ActivityThread中還存在一個(gè)該Looper的處理對(duì)象Hander H。從傳送的參數(shù)H.BIND_APPLICATION可以看到,這個(gè)消息就是發(fā)送給這個(gè)H來處理的。

一旦H接收到這個(gè)消息就開始創(chuàng)建Application了。這個(gè)過程是在handleBindApplication()中完成的:


private void handleBindApplication(AppBindData data) {

    ...

    mInstrumentation = (Instrumentation)

        cl.loadClass(data.instrumentationName.getClassName())

        .newInstance();

    //通過反射初始化一個(gè)Instrumentation儀表。后面會(huì)介紹。

    ...

    Application app = data.info.makeApplication(data.restrictedBackupMode, null);

    //通過LoadedApp命令創(chuàng)建Application實(shí)例

    mInitialApplication = app;

    ...

    mInstrumentation.callApplicationOnCreate(app);

    //讓儀器調(diào)用Application的onCreate()方法

    ...

}

handleBindApplication()中比較關(guān)鍵的是上面幾句代碼。其中有個(gè)類Instrumentation,它在創(chuàng)建Application類之前進(jìn)行實(shí)例化。它能夠允許你監(jiān)視應(yīng)用程序和系統(tǒng)的所有交互。打開這個(gè)類你可以發(fā)現(xiàn),最終Apllication的創(chuàng)建,Activity的創(chuàng)建,以及生命周期都會(huì)經(jīng)過這個(gè)對(duì)象去執(zhí)行。簡(jiǎn)單點(diǎn)說,就是把這些操作包裝了一層。通過操作Instrumentation進(jìn)而實(shí)現(xiàn)上述的功能。這里實(shí)例化Instrumentation的方法是反射!而反射的ClassName是來自于從ActivityManagerService中通過ApplicationThread的代理傳過來的。

接我們著看mInstrumentation調(diào)用的方法callApplicationOnCreate(app):


public void callApplicationOnCreate(Application app) {

    app.onCreate();

}

該方法只是回調(diào)了一下Application 的onCreate()。這就是為什么它能夠起到監(jiān)控的作用。我們最熟悉的Activity的一些聲明周期的方法onCreate(),onStart()等等也是通過這樣來進(jìn)行回調(diào)的。

再回到


Application app = data.info.makeApplication(data.restrictedBackupMode, null);

看下調(diào)用的方法makeApplication(data.restrictedBackupMode, null):


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

    //通過儀表創(chuàng)建Application

    ...

}

這里首先通過反射找到了Application的類名。其次創(chuàng)建了Application的ContextImpl ,ContextImpl 其實(shí)Application的Context具體執(zhí)行的類,我們平時(shí)調(diào)用的Context有關(guān)的方法最后其實(shí)都是調(diào)用了ContextImpl 的對(duì)應(yīng)方法,這里不展開講了。之后就是通過剛才說的mInstrumentation來調(diào)用newApplication( cl, appClass, appContext)創(chuàng)建Application。具體該方法如下:


static public Application newApplication(Class clazz

    , Context context) throws InstantiationException

    , IllegalAccessException

    , ClassNotFoundException {

        Application app = (Application)clazz.newInstance();

        //反射創(chuàng)建,簡(jiǎn)單粗暴

        app.attach(context);

        //關(guān)注下這里,Application被創(chuàng)建后第一個(gè)調(diào)用的方法。

        //目的是為了綁定ContextImpl 。

        return app;

    }

至此終于將Application創(chuàng)建出來了。

3.4 創(chuàng)建及啟動(dòng)Activity

還記得之前的Application啟動(dòng)信號(hào)其實(shí)是AMS通過ApplicationThread的代理調(diào)用bindApplication()發(fā)送過來的嗎?了解Binder通信機(jī)制可以知道,一旦客戶端調(diào)用遠(yuǎn)程服務(wù)(此時(shí)AMS是客戶端,app是服務(wù)端),調(diào)用服務(wù)的線程調(diào)用服務(wù)后是會(huì)掛起直到服務(wù)調(diào)用完畢返回結(jié)果的。這邊創(chuàng)建完Application相當(dāng)于服務(wù)調(diào)用完畢了。此時(shí)AMS的對(duì)應(yīng)線程會(huì)接著往下執(zhí)行代碼以同樣的方法通過ApplicationThread的代理向ApplicationThread發(fā)起啟動(dòng)主Activity的請(qǐng)求,并且在ApplicationThread中向H發(fā)送一條LAUNCH_ACTIVITY的消息。然后H就開始了初始化Activity。

收到LAUNCH_ACTIVITY后H會(huì)調(diào)用handleLaunchActivity():


private void handleLaunchActivity(ActivityClientRecord r

    , Intent customIntent

    , String reason) {

    ...

    Activity a = performLaunchActivity(r, customIntent);

    //媽蛋!又封裝到另一個(gè)方法中創(chuàng)建了。

    ...

    if (a != null) {

        ...

        handleResumeActivity(r.token

        , false

        , r.isForward

        ,!r.activity.mFinished && !r.startsNotResumed

        , r.lastProcessedSeq, reason);

        //Activity創(chuàng)建成功就往onResume()走了!

        ...

    }

}

繼續(xù)往下看performLaunchActivity(r, customIntent):


private Activity performLaunchActivity(ActivityClientRecord r

    , Intent customIntent) {

    ...

    activity = mInstrumentation.newActivity(

        cl, component.getClassName(), r.intent);

    //通過mInstrumentation來創(chuàng)建Activity

    ...

    Application app = r.packageInfo.makeApplication(false

    , mInstrumentation);

    //獲取Application

    ...

    activity.attach(appContext

        , this

        , getInstrumentation()

        , r.token

        ,.ident

        , app

        , r.intent

        , r.activityInfo

        , title

        , r.parent

        , r.embeddedID

        , r.lastNonConfigurationInstances

        , config

        ,r.referrer

        , r.voiceInteractor

        , window);

    ...

    if (r.isPersistable()) {

        mInstrumentation.callActivityOnCreate(

          activity, r.state, r.persistentState);

    } else {

        mInstrumentation.callActivityOnCreate(activity, r.state);

    }

    //根據(jù)是否可持久化選擇onCreate()方法。

    ...

}

注意這句代碼:


activity = mInstrumentation.newActivity(

        cl, component.getClassName(), r.intent);

正如前面所說,Activity、Application的創(chuàng)建及生命周期都被承包給Instrumentation。所以由它來負(fù)責(zé)??纯磏ewActivity():


public Activity newActivity(ClassLoader cl, String className,

            Intent intent)

            throws InstantiationException

            , IllegalAccessException,

            ClassNotFoundException {

        return (Activity)cl.loadClass(className).newInstance();

        //反射實(shí)例化Activity而已

    }

其實(shí)就是通過反射實(shí)例化了Activity。

回到performLaunchActivity() 創(chuàng)建了Activity后 將之前創(chuàng)建出來的Application和Activity關(guān)聯(lián)。

接著我們看performLaunchActivity() 中的這段代碼:


if (r.isPersistable()) {

        mInstrumentation.callActivityOnCreate(

          activity, r.state, r.persistentState);

    } else {

        mInstrumentation.callActivityOnCreate(activity, r.state);

    }

根據(jù)是否可持久化選擇Activity的onCreate()方法。同樣是通過Instrumentation儀表來執(zhí)行onCreate()的。它兩分別對(duì)應(yīng)的onCreate()方法為:


onCreate(icicle, persistentState);

//可獲得持久化數(shù)據(jù)

onCreate(icicle);

//平時(shí)重寫的最多的。

至此,成功調(diào)用了Activity的onCreate()方法。其實(shí)之后的onStart(),onResume()等生命周期的方法也時(shí)類似這樣調(diào)用的。

4、總結(jié)

從桌面點(diǎn)擊圖標(biāo)到創(chuàng)建應(yīng)用進(jìn)程,再到創(chuàng)建Application,在到創(chuàng)建主Activity到最后調(diào)用onCreate()的流程大致如上文所述。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容