Android Activity啟動(dòng)過(guò)程-從桌面點(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)注如下過(guò)濾器的Activity:

image

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

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

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)程,通過(guò)Binder IPC向sytem_server進(jìn)程發(fā)起attachApplication請(qǐng)求。

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

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

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

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

2者铜、概念介紹

2.1 Launcher

如開(kāi)頭所說(shuō)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)接口,來(lái)接收用戶的輸入砾医。既然是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ā)送過(guò)來(lái)的請(qǐng)求其實(shí)是發(fā)送給system_server错邦。而SystemServer也是一個(gè)進(jìn)程探赫。所以這一過(guò)程其實(shí)涉及到了進(jìn)程間的通信,這邊的這一過(guò)程是采用Binder的方式來(lái)進(jìn)行的撬呢。system_server這個(gè)進(jìn)程是Android Framework層里面非常重要的一個(gè)進(jìn)程伦吠。系統(tǒng)里面重要的服務(wù)都是在這個(gè)進(jìn)程里面開(kāi)啟的,比如 ActivityManagerService倾芝、PackageManagerService讨勤、WindowManagerService等等箭跳。

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

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

除此之外掉冶,其實(shí)所有的Activity的開(kāi)啟真竖、暫停、關(guān)閉都需要AMS來(lái)控制厌小,所以我們說(shuō)恢共,AMS負(fù)責(zé)系統(tǒng)中所有Activity的生命周期。

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

2.3 zygote

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

在Android系統(tǒng)里面梢薪,zygote是一個(gè)進(jìn)程的名字蹬铺。Android是基于Linux System的,當(dāng)你的手機(jī)開(kāi)機(jī)的時(shí)候秉撇,Linux的內(nèi)核加載完成之后就會(huì)啟動(dòng)一個(gè)叫“init“的進(jìn)程甜攀。在Linux System里面,所有的進(jìn)程都是由init進(jìn)程fork出來(lái)的琐馆,我們的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)行之后谁撼,在這之后再開(kāi)啟App,就相當(dāng)于開(kāi)啟一個(gè)新的進(jìn)程滋饲。而為了實(shí)現(xiàn)資源共用和更快的啟動(dòng)速度厉碟,Android系統(tǒng)開(kāi)啟新進(jìn)程的方式,是通過(guò)fork第一個(gè)zygote進(jìn)程實(shí)現(xiàn)的屠缭。所以說(shuō)箍鼓,除了第一個(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)用程序的開(kāi)始可以說(shuō)就是從ActivityThread.java中的main()方法開(kāi)始的富腊。下面是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()方法。從這也可以想象到為什么說(shuō)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接口球化。打開(kāi)源碼你會(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來(lái)代理間接進(jìn)行的。這樣設(shè)計(jì)的好處是保護(hù)了mRemote陆淀,并且能夠在操作mRemote前執(zhí)行一些別的事務(wù)考余,并且我們是以IActivityManager的身份來(lái)進(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);

    //先檢查一下有沒(méi)有

    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è)代理之后就可以作為客戶端通過(guò)Binder機(jī)制將app作為客戶端剿配,ActivityManagerService作為服務(wù)端來(lái)進(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è)變量中途被修改年扩,也說(shuō)明其的重要性蚁廓。ApplicationThread類繼承自ApplicationThreadNative。并且ApplicationThread是ActivityThread的一個(gè)內(nèi)部類厨幻。從設(shè)計(jì)角度可以看出相嵌,該類是專門(mén)讓ActivityThread來(lái)使用的一個(gè)類。

看一下ApplicationThread的父類ApplicationThreadNative:


public abstract class ApplicationThreadNative extends Binder

    implements IApplicationThread{

...

}

我們從ApplicationThreadNative看到它也是一個(gè)Binder况脆,同時(shí)實(shí)現(xiàn)了IApplicationThread接口饭宾。這個(gè)Binder并不是Binder代理,這個(gè)Binder說(shuō)明了應(yīng)用程序在作為客戶端的同時(shí)格了,也作為了服務(wù)端看铆。而作為服務(wù)端的Binder就是ApplicationThread。而 mgr.attachApplication(mAppThread) 這行代碼就是通過(guò)mgr將ApplicationThread的信息作為數(shù)據(jù)發(fā)送給AMS盛末,方便日后AMS通過(guò)ApplicationThread的代理發(fā)送數(shù)據(jù)給ApplicationThread來(lái)達(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)過(guò)一系列的操作,最終被調(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的代理宵荒,通過(guò)Binder進(jìn)程間通信調(diào)用app進(jìn)程的ApplicationThread的bindApplication()方法。該方法里面有一句關(guān)鍵代碼


sendMessage(H.BIND_APPLICATION, data);

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

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


private void handleBindApplication(AppBindData data) {

    ...

    mInstrumentation = (Instrumentation)

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

        .newInstance();

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

    ...

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

    //通過(guò)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)的所有交互架谎。打開(kāi)這個(gè)類你可以發(fā)現(xiàn)炸宵,最終Apllication的創(chuàng)建,Activity的創(chuàng)建谷扣,以及生命周期都會(huì)經(jīng)過(guò)這個(gè)對(duì)象去執(zhí)行土全。簡(jiǎn)單點(diǎn)說(shuō),就是把這些操作包裝了一層会涎。通過(guò)操作Instrumentation進(jìn)而實(shí)現(xiàn)上述的功能裹匙。這里實(shí)例化Instrumentation的方法是反射!而反射的ClassName是來(lái)自于從ActivityManagerService中通過(guò)ApplicationThread的代理傳過(guò)來(lái)的末秃。

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


public void callApplicationOnCreate(Application app) {

    app.onCreate();

}

該方法只是回調(diào)了一下Application 的onCreate()概页。這就是為什么它能夠起到監(jiān)控的作用。我們最熟悉的Activity的一些聲明周期的方法onCreate()练慕,onStart()等等也是通過(guò)這樣來(lái)進(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);

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

    ...

}

這里首先通過(guò)反射找到了Application的類名徽曲。其次創(chuàng)建了Application的ContextImpl ,ContextImpl 其實(shí)Application的Context具體執(zhí)行的類麸塞,我們平時(shí)調(diào)用的Context有關(guān)的方法最后其實(shí)都是調(diào)用了ContextImpl 的對(duì)應(yīng)方法秃臣,這里不展開(kāi)講了。之后就是通過(guò)剛才說(shuō)的mInstrumentation來(lái)調(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)建出來(lái)了。

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

還記得之前的Application啟動(dòng)信號(hào)其實(shí)是AMS通過(guò)ApplicationThread的代理調(diào)用bindApplication()發(fā)送過(guò)來(lái)的嗎偎捎?了解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í)行代碼以同樣的方法通過(guò)ApplicationThread的代理向ApplicationThread發(fā)起啟動(dòng)主Activity的請(qǐng)求丈牢,并且在ApplicationThread中向H發(fā)送一條LAUNCH_ACTIVITY的消息祭钉。然后H就開(kāi)始了初始化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);

    //通過(guò)mInstrumentation來(lái)創(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);

正如前面所說(shuō)垮卓,Activity垫桂、Application的創(chuàng)建及生命周期都被承包給Instrumentation。所以由它來(lái)負(fù)責(zé)扒接。看看newActivity():


public Activity newActivity(ClassLoader cl, String className,

            Intent intent)

            throws InstantiationException

            , IllegalAccessException,

            ClassNotFoundException {

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

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

    }

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

回到performLaunchActivity() 創(chuàng)建了Activity后 將之前創(chuàng)建出來(lái)的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()方法。同樣是通過(guò)Instrumentation儀表來(lái)執(zhí)行onCreate()的蒙挑。它兩分別對(duì)應(yīng)的onCreate()方法為:


onCreate(icicle, persistentState);

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

onCreate(icicle);

//平時(shí)重寫(xiě)的最多的宗侦。

至此,成功調(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)系作者
  • 序言:七十年代末察皇,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子泽台,更是在濱河造成了極大的恐慌什荣,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怀酷,死亡現(xiàn)場(chǎng)離奇詭異稻爬,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)蜕依,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)桅锄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人样眠,你說(shuō)我怎么就攤上這事竞滓。” “怎么了吹缔?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵商佑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我厢塘,道長(zhǎng)茶没,這世上最難降的妖魔是什么肌幽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮抓半,結(jié)果婚禮上喂急,老公的妹妹穿的比我還像新娘。我一直安慰自己笛求,他們只是感情好廊移,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著探入,像睡著了一般狡孔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蜂嗽,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天苗膝,我揣著相機(jī)與錄音,去河邊找鬼植旧。 笑死辱揭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的病附。 我是一名探鬼主播问窃,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼完沪!你這毒婦竟也來(lái)了泡躯?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤丽焊,失蹤者是張志新(化名)和其女友劉穎较剃,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體技健,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡写穴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雌贱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啊送。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖欣孤,靈堂內(nèi)的尸體忽然破棺而出馋没,到底是詐尸還是另有隱情,我是刑警寧澤降传,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布篷朵,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏声旺。R本人自食惡果不足惜笔链,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望腮猖。 院中可真熱鬧鉴扫,春花似錦、人聲如沸澈缺。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)莱预。三九已至,卻和暖如春雏吭,著一層夾襖步出監(jiān)牢的瞬間陪踩,已是汗流浹背杖们。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工摘完, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人傻谁。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像审磁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子态蒂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容