-
安卓系統(tǒng)中,組件踢代,應(yīng)用,與進(jìn)程的關(guān)系:
- 一個(gè)組件需要依附于一個(gè)應(yīng)用(其對(duì)應(yīng)Application類必須先初始化戒劫,ContentProvider除外半夷,看后面)
- 一個(gè)應(yīng)用可以擁有多個(gè)進(jìn)程(其Application對(duì)象在每個(gè)進(jìn)程中被初始化一遍)
- 一個(gè)進(jìn)程可以承載多個(gè)應(yīng)用 (一個(gè)進(jìn)程可以擁有多個(gè)Application對(duì)象)
-
例子:
- 通常情況婆廊,一個(gè)應(yīng)用運(yùn)行與一個(gè)進(jìn)程,對(duì)應(yīng)一個(gè)Application對(duì)象
- 一個(gè)應(yīng)用中巫橄,某些組件在注冊(cè)清單中指定了不同進(jìn)程淘邻,則啟動(dòng)時(shí)會(huì)將這些組件在對(duì)應(yīng)進(jìn)程中啟動(dòng),且在這之前湘换,會(huì)在每個(gè)對(duì)應(yīng)進(jìn)程中初始化這個(gè)應(yīng)用的Application對(duì)象宾舅。
- 一個(gè)進(jìn)程承載多個(gè)應(yīng)用,若多個(gè)應(yīng)用指定相同UID彩倚,且擁有相同簽名筹我,則這些應(yīng)用可以運(yùn)作在同一個(gè)進(jìn)程,則每個(gè)應(yīng)用的Application都會(huì)在這個(gè)進(jìn)程中初始化
四大組件的啟動(dòng)都涉及到進(jìn)程和應(yīng)用的啟動(dòng)帆离,我們這里以最常見的Activity的啟動(dòng)來解析安卓應(yīng)用的啟動(dòng)流程蔬蕊,以下是Activity的啟動(dòng)分類:
四種判斷結(jié)果分別各舉一例情況:
- Activity已經(jīng)以SingleTask,SingleTop哥谷,SingleInstance 模式啟動(dòng)岸夯,當(dāng)有其它意圖再次啟動(dòng)該Activity 時(shí),不再重復(fù)創(chuàng)建實(shí)例们妥,當(dāng)前Activity走onNewIntent方法猜扮,獲取外部傳入的數(shù)據(jù),并根據(jù)當(dāng)前Activity所處的情況监婶,走其它生命周期旅赢。
- Activity以普通啟動(dòng)模式,此情況為一般情況压储,直接創(chuàng)建Activity實(shí)例鲜漩,并走生命周期。
- UserId和簽名相同的應(yīng)用可以運(yùn)行于同一個(gè)進(jìn)程中集惋,當(dāng)需要啟動(dòng)應(yīng)用時(shí)孕似,若判斷出這個(gè)進(jìn)程已經(jīng)啟動(dòng),則在對(duì)應(yīng)進(jìn)程中刮刑,完成應(yīng)用的Application的實(shí)例化和生命周期喉祭,再完成Activity的實(shí)例化與生命周期。
- 在進(jìn)程也不存在的情況下雷绢,則先讓進(jìn)程啟動(dòng)泛烙,完成初始化工作,再在進(jìn)程完成Application的實(shí)例化與生命周期翘紊,再讓后完成Activity的實(shí)例化與生命周期蔽氨。
以下具體分析第四種情況,即需要啟動(dòng)的Activity所需依附的進(jìn)程未啟動(dòng)
概念明確:
- 安卓的四大組件的管理全部由ActivityManagerService(以下簡稱AMS)及其幾個(gè)協(xié)助類完成,啟動(dòng)Activity時(shí)鹉究,我們需要向AMS發(fā)出我們的啟動(dòng)意圖宇立,AMS會(huì)解析意圖,并作出對(duì)應(yīng)的處理自赔。
- Binder作為安卓的IPC機(jī)制妈嘹,其分為C/S兩端。Server端接收Client端發(fā)過來的數(shù)據(jù)并作出處理绍妨,并返回處理結(jié)果润脸。
- Binder服務(wù)端的對(duì)象,當(dāng)被Binder客戶端跨進(jìn)程調(diào)用時(shí)他去,其方法的執(zhí)行是在Binder線程里毙驯。
- Binder分為匿名Binder和有名Binder,有名可以直接通過ServiceManager獲取孤页,即通過鍵名查詢到對(duì)應(yīng)的Binder尔苦。匿名Binder未將自己注冊(cè)到ServiceManager,所以不能通過鍵名獲取到行施。
- AMS本身為Binder子類允坚,為一個(gè)Binder服務(wù)端,工作在system_server進(jìn)程蛾号,其在系統(tǒng)啟動(dòng)時(shí)將自己注冊(cè)入ServiceManager稠项,所以其為有名Binder,與服務(wù)端對(duì)應(yīng)的客戶端BinderProxy對(duì)象存在于各個(gè)應(yīng)用進(jìn)程里鲜结,但通常使用其封裝類ActivityManagerProxy(AMP)展运,與AMS完成遠(yuǎn)程調(diào)用。
- Binder可以通過Binder傳遞精刷,要使用匿名Binder拗胜,需要先利用其它Binder獲取到這個(gè)匿名Binder,如應(yīng)用進(jìn)程就在啟動(dòng)時(shí)將自己的匿名Binder ApplicationThread通過AMS/AMP傳遞給了system_server進(jìn)程怒允,這樣system_server進(jìn)程就存有了應(yīng)用進(jìn)程的Binder客戶端埂软,可以通過這個(gè)客戶端調(diào)用應(yīng)用進(jìn)程的方法,從而實(shí)現(xiàn)對(duì)應(yīng)用的管理纫事。
- Instrumentation勘畔,用于管理應(yīng)用程序和系統(tǒng)(主要與應(yīng)用程序內(nèi)的Activity)的交互過程,如startActivity時(shí)由Instrumentation對(duì)象將請(qǐng)求發(fā)往AMS,而系統(tǒng)對(duì)組件管理通Instrumentation對(duì)象實(shí)現(xiàn)丽惶,如Activity對(duì)象創(chuàng)建與生命周期的調(diào)用炫七,Instrumentation將在應(yīng)用初始化時(shí)被初始化,每個(gè)進(jìn)程只會(huì)存在一個(gè)Instrumentation對(duì)象钾唬,且每個(gè)Activity都有此對(duì)象的引用万哪,
- AMS 對(duì)四大組件的管理具體實(shí)現(xiàn)是由幾個(gè)類的協(xié)助完成的侠驯,ActivityStarter對(duì)應(yīng)Activity,ActiveService 對(duì)應(yīng)service壤圃,BroadcastQueue對(duì)應(yīng)Broadcast陵霉。與Activity相關(guān)還涉及到ActivityStack和ActivityStackSupervisor,負(fù)責(zé)Activity伍绳,Task與Stack管理,Activity啟動(dòng)過程中乍桂,AMS冲杀,ActivityStarter,ActivityStack睹酌,ActivityStackSupervisor需要協(xié)同工作权谁,以下我們稱這幾個(gè)類為AMS模塊。
- ActivityThread憋沿,與其內(nèi)部類ApplicationThread協(xié)同旺芽,與AMS交互,其mian方法可以理解為應(yīng)用進(jìn)程的根方法辐啄,進(jìn)程初始化完成后主線程會(huì)進(jìn)入Looper循環(huán)采章,開始接收ApplicationThread轉(zhuǎn)發(fā)過來的消息。
- ApplicationThread壶辜,Binder子類悯舟,匿名Binder,作為Binder服務(wù)端砸民,接收AMS發(fā)過來的消息抵怎,由于服務(wù)端的方法在Binder調(diào)用時(shí)都運(yùn)行在Binder線程,所以需要再通過Hander轉(zhuǎn)發(fā)到主線程中岭参,ApplicationThread接收到的調(diào)用都會(huì)通過Handler再轉(zhuǎn)到主線程中處理反惕,對(duì)應(yīng)的處理方法都是ActivityThread的方法。
啟動(dòng)流程:
-
從startActivity開始演侯,Activity重寫了Context的startActivity方法姿染,但大致流程是不變的,以下為Lancher應(yīng)用啟動(dòng)一個(gè)應(yīng)用時(shí)主線程的調(diào)用棧:
可以看出:
- Activity的startActivity走了startActivityForResult方法
- startActivityForResult調(diào)用了Instrumentation的execStartActivity方法
- Instrumentation 最終調(diào)用AMP的startActivity蚌本,AMP會(huì)將Intent傳遞給AMS盔粹,所以現(xiàn)在system_server進(jìn)程里就會(huì)有一個(gè)Binder線程會(huì)去調(diào)用AMS的startActivity 方法,這次調(diào)用中做了幾件重要的事:
- 解析Intent程癌,并根據(jù)pkms掃描到的信息舷嗡,創(chuàng)建對(duì)應(yīng)的ActivityRecord,每一個(gè)ActivityRecord對(duì)應(yīng)一個(gè)應(yīng)用進(jìn)程中的Activity實(shí)例嵌莉,ActivityRecord中還會(huì)創(chuàng)建這個(gè)Activity對(duì)應(yīng)的唯一的token进萄,其會(huì)在Activity創(chuàng)建時(shí)被傳遞給對(duì)應(yīng)的Activity,
- 通知WMS,顯示startWindow 中鼠,即對(duì)應(yīng)應(yīng)用Activity的主題里面windowBackground對(duì)應(yīng)資源可婶,這個(gè)窗口由system_server進(jìn)程顯示,不必等到應(yīng)用進(jìn)程啟動(dòng)后再顯示援雇,所以其啟動(dòng)速度很快矛渴。
- 遠(yuǎn)程調(diào)用當(dāng)前前臺(tái)Activity的schedulePause方法,對(duì)應(yīng)Activity的主線程會(huì)走onPause生命周期惫搏。 走完后具温,其會(huì)再通知AMS,它已經(jīng)走完onPause筐赔,AMS開始準(zhǔn)備啟動(dòng)目標(biāo)Activity铣猩。
-
在ActivityStackSupervisor這個(gè)類中,判斷出 要啟動(dòng)的Activity所需要的進(jìn)程還未啟動(dòng)茴丰,所以需要先啟動(dòng)其進(jìn)程:
AMS 通知Zygote 進(jìn)程啟動(dòng)一個(gè)應(yīng)用進(jìn)程达皿,這個(gè)IPC是socket,Zygote 進(jìn)程收到消息后fork出一個(gè)進(jìn)程贿肩,這個(gè)進(jìn)程就是新的Activity所需依附的應(yīng)用進(jìn)程峦椰,應(yīng)用進(jìn)程被fork出來之后,將AMS傳遞過來的參數(shù)配置給自己尸曼,然后就會(huì)反射調(diào)用ActivityThread的main方法们何。
-
此時(shí)AMS對(duì)這個(gè)新進(jìn)程還是無感知的,需要新進(jìn)程主動(dòng)‘聯(lián)系’AMS控轿,所以進(jìn)程進(jìn)入ActivityThread的main之后冤竹,主要做兩件事:
-
實(shí)例化自身,進(jìn)而實(shí)例化其成員變量ApplicationThread(匿名Binder服務(wù)端)茬射,通過AMP遠(yuǎn)程調(diào)用AMS的attachApplication方法鹦蠕,把自己的ApplicationThread傳遞給AMS模塊,現(xiàn)在AMS就知道新進(jìn)程已經(jīng)創(chuàng)建完畢在抛,并得到了其ApplicationThread客戶端钟病,可以通過這個(gè)Binder遠(yuǎn)程管理應(yīng)用進(jìn)程。
final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore }
調(diào)用Looper.prepareMainLooper 準(zhǔn)備主線程Looper刚梭, Looper.loop() 進(jìn)入循環(huán)肠阱,等待外界發(fā)來消息,此時(shí)朴读,應(yīng)用的進(jìn)程初始化算完成屹徘,從被fork出來到配置參數(shù),到將自己注冊(cè)入AMS衅金,再Loop主線程進(jìn)入循環(huán)噪伊,等待外部消息簿煌。
-
-
啟動(dòng)Application:
以上完成了應(yīng)用進(jìn)程的初始化,AMS模塊在收到應(yīng)用進(jìn)程發(fā)過來消息后鉴吹,會(huì)連續(xù)做兩件事姨伟,應(yīng)用的啟動(dòng)和組件的啟動(dòng),這里就是Activity的啟動(dòng)豆励。
AMS收到應(yīng)用進(jìn)程準(zhǔn)備完畢的消息后夺荒,會(huì)通過傳遞過來的ApplicationThread,調(diào)用其bindApplication方法肆糕,然后在應(yīng)用進(jìn)程中般堆,ApplicationThread將這消息轉(zhuǎn)發(fā)給主線程,所以在ActivityThread中會(huì)走到handleBindApplication诚啃,這個(gè)方法里完成:
-
Application的實(shí)例化,在LoadedApk里面完成私沮,并添加到ActivityThead中的Application列表始赎。
try { java.lang.ClassLoader cl = getClassLoader(); if (!mPackageName.equals("android")) { initializeJavaContextClassLoader(); } ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); appContext.setOuterContext(app); } catch (Exception e) { if (!mActivityThread.mInstrumentation.onException(app, e)) { throw new RuntimeException( "Unable to instantiate application " + appClass + ": " + e.toString(), e); } } mActivityThread.mAllApplications.add(app); mApplication = app;
mInitialApplication = app;
并復(fù)制給mInitialApplication,這個(gè)變量保存安卓進(jìn)程中第一個(gè)啟動(dòng)的Application仔燕,如果多個(gè)應(yīng)用共享進(jìn)程造垛,那這個(gè)變量就是第一個(gè)啟動(dòng)的應(yīng)用的Application
ContentProvider的實(shí)例化和onCreate,并注冊(cè)到AMS
Application的onCreate
-
-
Activity的啟動(dòng)
bindApplication之后晰搀,AMS模塊接著就會(huì)調(diào)用realStartActivityLocked五辽,同樣是通過ApplicationThread,調(diào)用其scheduleLaunchActivity外恕,同樣通過Handler轉(zhuǎn)到主線程杆逗,調(diào)用ActivityThread的handleLaunchActivity 方法,這里這個(gè)方法里完成幾件事:
Activity的對(duì)象創(chuàng)建鳞疲,通過Instrumentation完成
調(diào)用Activity的attach罪郊,這里面會(huì)將一個(gè)contextImpl對(duì)象傳遞給Activity,Activity本身是ContextWrapper尚洽,很多操作是委托給contextImpl完成的悔橄,同時(shí)還會(huì)創(chuàng)PhoneWindow對(duì)象作為成員變量
-
走生命周期
if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } //////////////////// if (!r.activity.mFinished) { activity.performStart(); } //////////////////// performResumeActivity(token, clearHide);
分別會(huì)調(diào)用Activity的onCreate,onStart腺毫,onResume癣疟,方法
-
將視圖添加到WMS
從PhoneWindow拿到DecorView,調(diào)用WindowManager的addView潮酒,addView里面會(huì)走到WindowManagerGlobal里面睛挚,創(chuàng)建ViewRootImpl,完成與WMS的通信澈灼,之后開始繪制視圖
r.window = r.activity.getWindow(); View decor = r.window.getDecorView(); decor.setVisibility(View.INVISIBLE); ViewManager wm = a.getWindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); a.mDecor = decor; l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; if (a.mVisibleFromClient) { a.mWindowAdded = true; wm.addView(decor, l); }