1狂票、概述
當(dāng)用戶從桌面點擊一個應(yīng)用圖標(biāo)時薄风,該應(yīng)用就會啟動并顯示主Activity君仆,即在AndroidManifest中標(biāo)注如下過濾器的Activity:
里面的category中涉及到LAUNCHER丐一。這個其實和Laucher進程有關(guān)卓练,這是一個桌面進程。所以從桌面點擊圖標(biāo)到應(yīng)用啟動顯示的頁面的過程晒哄,其實就是從一個應(yīng)用啟動到另一個應(yīng)用的過程睁宰。
總體流程大致如下圖所示:
① 點擊桌面App圖標(biāo),Launcher進程采用Binder IPC向system_server進程發(fā)起startActivity請求寝凌。
② system_server進程接收到請求后柒傻,向zygote進程發(fā)送創(chuàng)建進程的請求。
③ Zygote進程fork出新的子進程较木,即App進程红符。
④ App進程,通過Binder IPC向sytem_server進程發(fā)起attachApplication請求。
⑤ system_server進程在收到請求后预侯,進行一系列準(zhǔn)備工作后致开,再通過binder IPC向App進程發(fā)送scheduleLaunchActivity請求。
⑥ App進程的binder線程(ApplicationThread)在收到請求后雌桑,通過handler向主線程發(fā)送LAUNCH_ACTIVITY消息喇喉。
⑦ 主線程在收到Message后,通過發(fā)射機制創(chuàng)建目標(biāo)Activity校坑,并回調(diào)Activity.onCreate()等方法拣技。
⑧ 到此,App便正式啟動耍目,開始進入Activity生命周期膏斤,執(zhí)行完onCreate/onStart/onResume方法,UI渲染結(jié)束后便可以看到App的主界面邪驮。
2莫辨、概念介紹
2.1 Launcher
如開頭所說Launcher本質(zhì)上也是一個應(yīng)用程序,和我們的App一樣毅访,同時桌面顯示的頁面也是一個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這個Activity實現(xiàn)了點擊沮榜、長按等回調(diào)接口,來接收用戶的輸入喻粹。既然是Activity蟆融,那么從Launcher的Activity跳轉(zhuǎn)到我們應(yīng)用的主Activity,和我們平時從一個Activity跳轉(zhuǎn)到另一個Activity的其實從代碼角度一樣守呜。即捕捉圖標(biāo)點擊事件型酥,然后startActivity()發(fā)送對應(yīng)的Intent請求。
2.2 system_server
startActivity()發(fā)送過來的請求其實是發(fā)送給system_server查乒。而SystemServer也是一個進程弥喉。所以這一過程其實涉及到了進程間的通信,這邊的這一過程是采用Binder的方式來進行的玛迄。system_server這個進程是Android Framework層里面非常重要的一個進程由境。系統(tǒng)里面重要的服務(wù)都是在這個進程里面開啟的,比如 ActivityManagerService蓖议、PackageManagerService藻肄、WindowManagerService等等。
而今天重點要涉及到ActivityManagerService這個服務(wù)拒担,其簡稱AMS。ActivityManagerService進行初始化的時機很明確攻询,就是在SystemServer進程開啟的時候从撼,就會初始化ActivityManagerService。
我們的App通過調(diào)用startActivity()并不能直接打開另外一個App,這個方法會通過一系列的調(diào)用低零,最后告訴AMS說:“我要打開這個App婆翔,我知道他的住址和名字,你幫我打開吧掏婶!”所以是AMS來通知zygote進程來fork一個新進程啃奴,來開啟我們的目標(biāo)App。
除此之外雄妥,其實所有的Activity的開啟最蕾、暫停、關(guān)閉都需要AMS來控制老厌,所以我們說瘟则,AMS負(fù)責(zé)系統(tǒng)中所有Activity的生命周期。
在Android系統(tǒng)中枝秤,任何一個Activity的啟動都是由AMS和應(yīng)用程序進程相互配合來完成的醋拧。AMS服務(wù)統(tǒng)一調(diào)度系統(tǒng)中所有進程的Activity啟動,而每個Activity的啟動過程則由其所屬的進程具體來完成淀弹。
2.3 zygote
如上所說丹壕,ActivityManagerService收到一個打開一個應(yīng)用程序的通知后會發(fā)送創(chuàng)建進程的請求給到zygote來創(chuàng)建一個app進程。
在Android系統(tǒng)里面薇溃,zygote是一個進程的名字菌赖。Android是基于Linux System的,當(dāng)你的手機開機的時候痊焊,Linux的內(nèi)核加載完成之后就會啟動一個叫“init“的進程盏袄。在Linux System里面,所有的進程都是由init進程fork出來的薄啥,我們的zygote進程也不例外辕羽。
我們都知道,每一個App其實都是一個單獨的dalvik虛擬機并對應(yīng)一個單獨的進程垄惧。所以當(dāng)系統(tǒng)里面的第一個zygote進程運行之后刁愿,在這之后再開啟App,就相當(dāng)于開啟一個新的進程到逊。而為了實現(xiàn)資源共用和更快的啟動速度铣口,Android系統(tǒng)開啟新進程的方式,是通過fork第一個zygote進程實現(xiàn)的觉壶。所以說脑题,除了第一個zygote進程,其他應(yīng)用所在的進程都是zygote的子進程铜靶。而zygote的直白翻譯為“受精卵”叔遂,也是很形象生動了。
而創(chuàng)建的新進程的入口就是ActivityThread.main()方法,之后的部分將著重介紹已艰。
3痊末、應(yīng)用創(chuàng)建到顯示
3.1 啟動應(yīng)用程序
Android中,一個應(yīng)用程序的開始可以說就是從ActivityThread.java中的main()方法開始的哩掺。下面是main()比較關(guān)鍵的代碼:
public static void main(String[] args){
...
Looper.prepareMainLooper();
//初始化Looper
...
ActivityThread thread = new ActivityThread();
//實例化一個ActivityThread
thread.attach(false);
//這個方法最后就是為了發(fā)送出創(chuàng)建Application的消息
...
Looper.loop();
//主線程進入無限循環(huán)狀態(tài)凿叠,等待接收消息
}
從源碼中可以看到,main()方法中主要做的事情是嚼吞,初始化主線程的Looper盒件、主Handler。并使主線程進入等待接收Message消息的無限循環(huán)狀態(tài)誊薄。并在進入等待接收消息前實例化一個實例化一個ActivityThread履恩,并調(diào)用其attach()方法。從這也可以想象到為什么說Android的設(shè)計是一個事件驅(qū)動的模型了呢蔫。
3.2 應(yīng)用程序和AMS關(guān)聯(lián)
我們在看一下thread.attach(false)中的關(guān)鍵代碼:
public void attach(boolean system){
...
final IActivityManager mgr = ActivityManagerNative.getDefault();
//獲得IActivityManager實例
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
}
里面的IActivityManager 是一個接口切心,當(dāng)我們調(diào)用ActivityManagerNative.getDefault()獲得的實際是一個代理類的實例——ActivityManagerProxy,這個東西實現(xiàn)了IActivityManager接口片吊。打開源碼你會發(fā)現(xiàn)绽昏,ActivityManagerProxy是ActivityManagerNative的一個內(nèi)部類。既然是一個代理類它必定有代理的對象俏脊。查看一下ActivityManagerProxy的構(gòu)造函數(shù):
public ActivityManagerProxy(IBinder remote) {
mRemote = remote;
}
這個構(gòu)造函數(shù)非常的簡單全谤。首先它需要一個IBinder參數(shù),然后賦值給mRemote變量爷贫。這個mRemote顯然是ActivityManagerNative的成員變量认然。但對它的操作是由ActivityManagerProxy來代理間接進行的。這樣設(shè)計的好處是保護了mRemote漫萄,并且能夠在操作mRemote前執(zhí)行一些別的事務(wù)卷员,并且我們是以IActivityManager的身份來進行這些操作。
該構(gòu)造函數(shù)的調(diào)用地點:
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);
//這個地方調(diào)用了構(gòu)造函數(shù)
}
上面這個方法是ActivityManagerNative中的一個靜態(tài)方法腾务,它會調(diào)用到ActivityManagerProxy的構(gòu)造方法毕骡。這個靜態(tài)方法也需要一個IBinder作為參數(shù)。
查找這個函數(shù)的調(diào)用地點以及傳入的參數(shù)到底是什么:
private static final SingletongDefault = new Singleton() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
//重點把沂荨未巫!IBinder實例就是在這里獲得的。
...
IActivityManager am = asInterface(b);
//調(diào)用了上面的方法启昧。
...
return am;
}
};
這是ActivityManagerNative的靜態(tài)常量叙凡,它是一個單例。在其中終于獲得了前面一直在用的IBinder實例密末。
IBinder b = ServiceManager.getService("activity");
到這里應(yīng)該已經(jīng)非常清晰了握爷,IActivityManager 獲取到的就是一個ActivityManagerService的代理宰啦。有了這個代理之后就可以作為客戶端通過Binder機制將app作為客戶端,ActivityManagerService作為服務(wù)端來進行通信了饼拍。具體Binder進程間通信機制請看我之前一篇文章:Binder進程間通信機制。
我們回到前面的thread.attach(false)方法中田炭,接著往下看在獲得IActivityManager實例之后师抄,將會執(zhí)行它的attachApplication(mAppThread)方法。該方法會傳入一個mAppThread參數(shù)教硫。在ActivityThread這個類的成員變量中叨吮,有這么一行代碼:
final ApplicationThread mAppThread = new ApplicationThread();
ApplicationThread是作為ActivityThread中的一個常量出現(xiàn)的。這表明系統(tǒng)不希望這個變量中途被修改瞬矩,也說明其的重要性茶鉴。ApplicationThread類繼承自ApplicationThreadNative。并且ApplicationThread是ActivityThread的一個內(nèi)部類景用。從設(shè)計角度可以看出涵叮,該類是專門讓ActivityThread來使用的一個類。
看一下ApplicationThread的父類ApplicationThreadNative:
public abstract class ApplicationThreadNative extends Binder
implements IApplicationThread{
...
}
我們從ApplicationThreadNative看到它也是一個Binder伞插,同時實現(xiàn)了IApplicationThread接口割粮。這個Binder并不是Binder代理,這個Binder說明了應(yīng)用程序在作為客戶端的同時媚污,也作為了服務(wù)端舀瓢。而作為服務(wù)端的Binder就是ApplicationThread。而 mgr.attachApplication(mAppThread) 這行代碼就是通過mgr將ApplicationThread的信息作為數(shù)據(jù)發(fā)送給AMS耗美,方便日后AMS通過ApplicationThread的代理發(fā)送數(shù)據(jù)給ApplicationThread來達到控制app的Activity生命周期等一系列操作京髓。
幾經(jīng)輾轉(zhuǎn),ApplicationThread的信息終于傳遞到了AMS中商架,我們可以從AMS的源碼中找到這個函數(shù):
private final boolean attachApplicationLocked(IApplicationThread thread
, int pid) {
...
thread.bindApplication();
...
}
3.3 創(chuàng)建Application
ApplicationThread以IApplicationThread的身份到了ActivityManagerService中(其實在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進程間通信調(diào)用app進程的ApplicationThread的bindApplication()方法。該方法里面有一句關(guān)鍵代碼
sendMessage(H.BIND_APPLICATION, data);
還記不記得最開始main函數(shù)創(chuàng)建的Looper皇型。而ActivityThread中還存在一個該Looper的處理對象Hander H诬烹。從傳送的參數(shù)H.BIND_APPLICATION可以看到,這個消息就是發(fā)送給這個H來處理的弃鸦。
一旦H接收到這個消息就開始創(chuàng)建Application了绞吁。這個過程是在handleBindApplication()中完成的:
private void handleBindApplication(AppBindData data) {
...
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName())
.newInstance();
//通過反射初始化一個Instrumentation儀表。后面會介紹唬格。
...
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
//通過LoadedApp命令創(chuàng)建Application實例
mInitialApplication = app;
...
mInstrumentation.callApplicationOnCreate(app);
//讓儀器調(diào)用Application的onCreate()方法
...
}
handleBindApplication()中比較關(guān)鍵的是上面幾句代碼家破。其中有個類Instrumentation颜说,它在創(chuàng)建Application類之前進行實例化。它能夠允許你監(jiān)視應(yīng)用程序和系統(tǒng)的所有交互汰聋。打開這個類你可以發(fā)現(xiàn)门粪,最終Apllication的創(chuàng)建,Activity的創(chuàng)建烹困,以及生命周期都會經(jīng)過這個對象去執(zhí)行玄妈。簡單點說,就是把這些操作包裝了一層髓梅。通過操作Instrumentation進而實現(xiàn)上述的功能拟蜻。這里實例化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()等等也是通過這樣來進行回調(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 其實Application的Context具體執(zhí)行的類愉老,我們平時調(diào)用的Context有關(guān)的方法最后其實都是調(diào)用了ContextImpl 的對應(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)建焰盗,簡單粗暴
app.attach(context);
//關(guān)注下這里,Application被創(chuàng)建后第一個調(diào)用的方法咒林。
//目的是為了綁定ContextImpl 熬拒。
return app;
}
至此終于將Application創(chuàng)建出來了。
3.4 創(chuàng)建及啟動Activity
還記得之前的Application啟動信號其實是AMS通過ApplicationThread的代理調(diào)用bindApplication()發(fā)送過來的嗎垫竞?了解Binder通信機制可以知道澎粟,一旦客戶端調(diào)用遠程服務(wù)(此時AMS是客戶端,app是服務(wù)端)欢瞪,調(diào)用服務(wù)的線程調(diào)用服務(wù)后是會掛起直到服務(wù)調(diào)用完畢返回結(jié)果的活烙。這邊創(chuàng)建完Application相當(dāng)于服務(wù)調(diào)用完畢了。此時AMS的對應(yīng)線程會接著往下執(zhí)行代碼以同樣的方法通過ApplicationThread的代理向ApplicationThread發(fā)起啟動主Activity的請求遣鼓,并且在ApplicationThread中向H發(fā)送一條LAUNCH_ACTIVITY的消息啸盏。然后H就開始了初始化Activity。
收到LAUNCH_ACTIVITY后H會調(diào)用handleLaunchActivity():
private void handleLaunchActivity(ActivityClientRecord r
, Intent customIntent
, String reason) {
...
Activity a = performLaunchActivity(r, customIntent);
//媽蛋骑祟!又封裝到另一個方法中創(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é)舟茶”蹋看看newActivity():
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException
, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
//反射實例化Activity而已
}
其實就是通過反射實例化了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()的型诚。它兩分別對應(yīng)的onCreate()方法為:
onCreate(icicle, persistentState);
//可獲得持久化數(shù)據(jù)
onCreate(icicle);
//平時重寫的最多的客燕。
至此,成功調(diào)用了Activity的onCreate()方法狰贯。其實之后的onStart()也搓,onResume()等生命周期的方法也時類似這樣調(diào)用的。
4涵紊、總結(jié)
從桌面點擊圖標(biāo)到創(chuàng)建應(yīng)用進程傍妒,再到創(chuàng)建Application,在到創(chuàng)建主Activity到最后調(diào)用onCreate()的流程大致如上文所述摸柄。