tips:部分讀者可能對(duì)此文會(huì)引起不適,若有此感陵刹,敬請(qǐng)?zhí)^默伍。
“我就知道你還會(huì)再來的,說吧衰琐,這次想學(xué)習(xí)什么也糊?”,還沒等我出聲羡宙,Story大神就開口了狸剃,“上一次我進(jìn)來是學(xué)到了不少知識(shí),而且app啟動(dòng)也優(yōu)化了不少狗热,但是這些都是表面的知識(shí)钞馁,我在優(yōu)化的過程中突然就想到了,我點(diǎn)擊圖標(biāo)的時(shí)候匿刮,app是怎么啟動(dòng)起來的僧凰?”我充滿疑問的問道,“哈哈熟丸,我就知道你是孺子可教也训措,你確定要深入虎穴嗎?這可是比較燒腦的環(huán)節(jié)哦光羞!”绩鸣,“確定!”狞山,我想都沒想就回答了全闷,為了追求未知的知識(shí),我還是比較堅(jiān)定的萍启。
虎穴总珠,打開!
就在這時(shí)勘纯,一堆代碼仿佛像掙脫了韁繩的馬一樣飛奔而來局服,并且整齊的列好隊(duì)排列在我眼前〔底瘢“請(qǐng)大家自我介紹一下”淫奔,Story大神對(duì)它們說道。
“你好堤结,我是 Zygote唆迁,我是Android系統(tǒng)創(chuàng)造出來的鸭丛,而我的作用就是為Android系統(tǒng)生孩子。
“我叫 ActivityManager唐责,一聽我的名字就知道我是一個(gè)Activity管理層(不單單是Activity的管理鳞溉,更是其他三大組件的管理者),無論是創(chuàng)建還是跳轉(zhuǎn)鼠哥,都要經(jīng)過我的審判熟菲,才能繼續(xù)下去,也就是說我掌握著Activity的生死大權(quán)朴恳。還有抄罕,你看到站在我身邊的都是我的手下,我左邊的這個(gè)是 IActivityManager于颖,它就是對(duì)我的命令進(jìn)行了封裝裝飾呆贿,我右手邊的是 ActivityManagerProxy ,它就是對(duì)封裝裝飾好的命令進(jìn)行下傳的森渐,而我后面的那位是 ActivityManagerService 榨崩,它就是要對(duì)命令執(zhí)行的人了,別看我衣著光鮮章母,其實(shí)還是挺累的母蛛,一個(gè)個(gè) 代理 著我的命令進(jìn)行傳遞〔式迹”
“大家好,我叫 ActivityThread 蚪缀, 我的職責(zé)是管理應(yīng)用進(jìn)程的主線程的執(zhí)行秫逝,比如快速處理UI界面的變化,還有一些需要在主線程上調(diào)度都是我的管轄范圍询枚∥シ”
“我是 Process ,想要進(jìn)程金蜀,就來我這里申領(lǐng)吧刷后。”
聽著它們講了一大堆渊抄,我一直在點(diǎn)頭尝胆,其實(shí)我內(nèi)心是懵逼的,這是什么跟什么啊护桦。貌似Story大神看出了我的疑問含衔,就對(duì)我說了,“是不是沒聽懂它們?cè)谡f什么?”贪染,我點(diǎn)點(diǎn)頭缓呛,“哈哈,來吧杭隙,走進(jìn)它們的世界看一下你就會(huì)了如指掌的了强经,過來吧,”我還是心懷疑慮的走了過去寺渗。
簡(jiǎn)直是走進(jìn)了Android系統(tǒng)的五章六腑,各個(gè)部門配合緊密兰迫,處理速度之迅猛信殊。“到了”汁果,Story大神帶我走進(jìn)了一個(gè)類似車間的一個(gè)工作室涡拘,眼前的那一幕是我從所未見的,當(dāng)然据德,自從進(jìn)來這里之后鳄乏,每次都會(huì)刷新我的世界觀和人生觀!
剛剛還在自我介紹的它們棘利,現(xiàn)在已經(jīng)在認(rèn)真地工作中了橱野,Zygote 正在分裂復(fù)制著(fork),真的像它剛剛介紹的那樣善玫,在生孩子水援,所有的應(yīng)用程序的進(jìn)程都是又它生出來的。這時(shí)候從中間浮出一段文字茅郎。
應(yīng)用程序的運(yùn)行蜗元,都是基于 Android的虛擬機(jī),而且每次啟動(dòng)都會(huì)帶來很大的開銷系冗,而 Zygote 的生產(chǎn)方式則能夠提升不小的效率奕扣。在這個(gè)生產(chǎn)的過程中,采用了Linux 的 寫時(shí)拷貝技術(shù) Copy-on-Write 的方式掌敬,重復(fù)利用了 Zygote 上的資源惯豆,達(dá)到了最大的效率。
首先奔害, Zygote 會(huì)開啟一個(gè)Socket:registerZygoteSocket(socketName)循帐,也就是Zygote Socket,這個(gè)Socket就是去監(jiān)聽?wèi)?yīng)用程序的請(qǐng)求的舀武,當(dāng)有請(qǐng)求的話就會(huì)立刻通知 Zygote 進(jìn)行生產(chǎn)拄养,同時(shí)還啟動(dòng)了 SystemServer 。
SystemServer ?這又是什么來的瘪匿?“剛剛因?yàn)樗α缩斯#詻]出來跟你打招呼,現(xiàn)在跟你介紹一下它吧”棋弥。
SystemServer 核偿,是 Zygote 的大兒子,在生產(chǎn)過程中扮演中無比重要的角色顽染,正如其名漾岳,系統(tǒng)中的所有服務(wù)都與它有著密切的關(guān)系,而且整個(gè)Android中的核心Service都在其中粉寞,比如剛剛跟你介紹的 ActivityManagerService 尼荆, Zygote 統(tǒng)管著后宮大權(quán)(生孩子),而 SystemServer 則是名副其實(shí)的一人之上萬人之下的統(tǒng)治者了唧垦!
緊接著捅儒, ActivityManager 出現(xiàn)了,只見最上層的編碼者(就是我了)振亮,點(diǎn)擊了app巧还,這時(shí), ActivityManager 開發(fā)工作了坊秸,發(fā)出 startActivity(intent) 的命令麸祷,app啟動(dòng)了,而在系統(tǒng)中褒搔,又多了一個(gè)進(jìn)程出來摇锋,而系統(tǒng)又是一個(gè)進(jìn)程,那么這個(gè)命令就由中間的管理服務(wù)者
ActivityManagerService來調(diào)度了站超,而這是屬于兩個(gè)進(jìn)程間的通信荸恕,又設(shè)計(jì)到了跨進(jìn)程通信了(IPC)。
掌權(quán)者 ActivityManager 是所有人都能看得到權(quán)力所有者死相,對(duì)接著所有的程序員融求,下發(fā)了命令之后通過 IActivityManager 的修飾封裝,比如 startActivity 算撮、finishActivity等命令生宛,通過 ActivityManagerProxy 把命令傳遞到執(zhí)行者 ActivityManagerService 手中,再進(jìn)行相應(yīng)的處理肮柜。
還不明白嗎陷舅?我們從上至下再詳細(xì)講解下這個(gè)流程吧。
當(dāng)我們點(diǎn)擊App時(shí)审洞,調(diào)用了Activity的startActivity莱睁,接著調(diào)用了startActivityForResult。
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null); // <------調(diào)用
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options); // <------調(diào)用
} else {
startActivityForResult(intent, -1);
}
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);// <------調(diào)用 來到這里: mInstrumentation.execStartActivity!Q鼋恕创淡!
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
看到代碼,會(huì)調(diào)用startActivityForResult中的 mInstrumentation.execStartActivity南吮,那這個(gè)Instrumentation又是有什么作用的呢琳彩?一環(huán)套著一環(huán)!
遠(yuǎn)處慢慢飄來Instrumentation的介紹部凑。
Base class for implementing application instrumentation code. When running with instrumentation turned on, this class will be instantiated for you before any of the application code, allowing you to monitor all of the interaction the system has with the application. An Instrumentation implementation is described to the system through an AndroidManifest.xml's <instrumentation> tag.
這個(gè)是Android系統(tǒng)對(duì)它的一個(gè)定義露乏,說了什么呢?我們來翻譯一下涂邀,現(xiàn)在知道英語好的重要性了嗎瘟仿?
用于實(shí)現(xiàn)應(yīng)用程序代碼的基類。當(dāng)使用Instrumentation進(jìn)行運(yùn)行時(shí)必孤,該類將在任何應(yīng)用程序代碼之前為您實(shí)例化,允許您監(jiān)視系統(tǒng)與應(yīng)用程序之間的所有交互瑞躺。Instrumentation實(shí)現(xiàn)了系統(tǒng)通過AndroidManifest. xml的<instrumentation>標(biāo)簽敷搪。
簡(jiǎn)單來說 Instrumentation ,它擁有強(qiáng)大的跟蹤Application以及Activity生命周期的功能幢哨,而且一個(gè)應(yīng)用有且僅有一個(gè) Instrumentation赡勘,并且每個(gè)Activity都有一個(gè) Instrumentation 的引用。ActivityThread 要?jiǎng)?chuàng)建或暫停某個(gè)Activity時(shí)捞镰,都需要通過 Instrumentation 來進(jìn)行具體的操作闸与。
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
// 自動(dòng)屏蔽一些不重要的代碼,易于查看重點(diǎn)內(nèi)容0妒邸践樱!
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
我們又發(fā)現(xiàn)了 startActivity 這個(gè)方法,剛剛我們說到了凸丸, Instrumentation 擁有強(qiáng)大的跟蹤Application以及Activity生命周期的功能拷邢,那么說吧,它就是完成對(duì)Application以及Activity初始化和管理生命周期的一個(gè)大管家屎慢,我就舉幾個(gè)例子給你看看瞭稼,什么叫證據(jù)!
public void callActivityOnStart(Activity activity) {
activity.onStart();
}
public void callActivityOnRestart(Activity activity) {
activity.onRestart();
}
public void callActivityOnResume(Activity activity) {
activity.mResumed = true;
activity.onResume();
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
am.match(activity, activity, activity.getIntent());
}
}
}
}
這些方法都是Acitivity生命周期的方法吧腻惠?所以說环肘,Instrumentation 是非常重要的,但是集灌,你會(huì)發(fā)現(xiàn)悔雹,這個(gè) Instrumentation 非常重要,你在編程的時(shí)候有用到這個(gè)東西嗎?并沒有荠商,可見它只是在背后默默地做出自己的奉獻(xiàn)寂恬!
介紹完 Instrumentation ,我們?cè)倩氐?execStartActivity 這個(gè)方法莱没,出現(xiàn)了一個(gè)新面孔 ActivityManagerNative 初肉,直接來看下它的代碼實(shí)現(xiàn)吧。
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
/**
* 將綁定對(duì)象插入活動(dòng)管理器接口饰躲,如果需要生成代理牙咏。
*/
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è)ActivityManagerProxy對(duì)象,而且傳遞了一個(gè)IBinder進(jìn)去嘹裂,這個(gè)IBidder就是用來進(jìn)行IPC通信的妄壶。
}
/**
* 檢索系統(tǒng)的默認(rèn)/全局活動(dòng)管理器。
*/
static public IActivityManager getDefault() {
return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
從上面的代碼我們可以了解到 ActivityManagerNative 是 Binder的一個(gè)子類寄狼,并且實(shí)現(xiàn)了IActivityManager 這個(gè)接口丁寄,得到 ActivityManagerProxy 這個(gè)對(duì)象,正如上面我們所說的:
下發(fā)了命令之后通過 IActivityManager 的修飾封裝泊愧, startActivity 這個(gè)命令伊磺,通過 ActivityManagerProxy 把命令傳遞到執(zhí)行者 ActivityManagerService 手中,再進(jìn)行相應(yīng)的處理删咱。
我們已經(jīng)到達(dá)了命令封裝屑埋,然后叫給傳達(dá)者 ActivityManagerProxy 這一步,接下來就是看傳達(dá)者 ActivityManagerProxy 如何將命令交給執(zhí)行者 ActivityManagerService 了痰滋。
我們走近一步摘能,來瞧一瞧 ActivityManagerProxy 中的startActivity()方法是如何編寫的。
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
相信你也可以看到敲街,通過傳到 ActivityManagerProxy 的IBinder团搞,利用這個(gè)對(duì)象,調(diào)用了transact()方法多艇,把所有參數(shù)封裝成了Parcel對(duì)象莺丑,這樣就向 ActivityManagerService 發(fā)射信號(hào)彈,進(jìn)行通信了墩蔓,執(zhí)行者 ActivityManagerService 收到指令后立馬進(jìn)行了處理梢莽。
我深吸一口氣,什么 Proxy 奸披、ActivityManagerService 等等一直在我腦海里回旋昏名,突然想起了一個(gè)設(shè)計(jì)模式好像就是這樣的啊,就是那個(gè)叫代理模式的阵面。
代理:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問轻局。在某些情況下洪鸭,一個(gè)對(duì)象不適合或者不能直接引用另一個(gè)對(duì)象,而代理對(duì)象可以在客戶端和目標(biāo)對(duì)象之間起到中介的作用仑扑。
對(duì)览爵,就是這樣的,看來今天的知識(shí)要好好消化一下了镇饮。
“等等蜓竹,先別想其他的,你以為到這一步就結(jié)束了嗎储藐?剛剛才到執(zhí)行者這邊呢俱济,還有一段路要走啊,我們接著看吧”钙勃,還有啊...我當(dāng)時(shí)的內(nèi)心是崩潰的蛛碌,還以為就這樣結(jié)束了。
當(dāng) ActivityManagerService 接收到指令之后辖源,正式開始啟動(dòng)Activity蔚携,這時(shí),ActivityManagerService 要作出嚴(yán)格的審核過程克饶。只見它把指令轉(zhuǎn)換為了 ResolveInfo 酝蜒。
ResolveInfo:從一個(gè)intent對(duì)應(yīng)的IntentFilter所解析獲取的信息。這部分地對(duì)應(yīng)于從AndroidManifest .xml的<intent>標(biāo)簽彤路。
然后 ActivityManagerService 調(diào)用 startActivityLocked() 方法進(jìn)行下一步秕硝,再來到startSpecificActivityLocked() 方法芥映,這時(shí)候就需要判斷是否需要?jiǎng)?chuàng)建一個(gè)全新的進(jìn)程洲尊,如果需要?jiǎng)t調(diào)用startProcessLocked() 方法進(jìn)行創(chuàng)建,而在這個(gè)方法的內(nèi)部有一個(gè)Process.start的方法奈偏,這個(gè)時(shí)候正式到了我們的 ActivityThread 的工作坞嘀,還記得在介紹 Zygote 時(shí)局义,它會(huì)打開一個(gè)Socket來監(jiān)聽需要?jiǎng)?chuàng)建 Process 的請(qǐng)求嗎雇盖? Zygote 會(huì)不斷取出建立的連接,再進(jìn)行 fork 進(jìn)程拄显,這就是我們的應(yīng)用進(jìn)程了裁蚁,而且返回了每個(gè)進(jìn)程所對(duì)應(yīng)的 process id矢渊,這時(shí)就回到了 ActivityThread ,眾所周知的UI線程枉证,進(jìn)行處理頁面的顯示矮男,它將和 ActivityManagerService 配合,一起完成接下來的工作室谚,比如activity的管理毡鉴。到此崔泵,整個(gè)應(yīng)用啟動(dòng)完畢,所有的工作就告一段落了猪瞬。
贈(zèng)一個(gè)高清大圖憎瘸!
虎穴,關(guān)閉陈瘦!
“好了幌甘,本章的學(xué)習(xí)就要結(jié)束了,回去好好回味一下吧甘晤,老規(guī)矩含潘,我還是要提一個(gè)問題給你,不過這個(gè)問題你可以回去好好想想的线婚,不用著急回答我”遏弱。
既然,我們從底層去學(xué)習(xí)了整個(gè)app的啟動(dòng)過程塞弊,那對(duì)于上一章所講到的優(yōu)化啟動(dòng)時(shí)間有什么作用呢漱逸?
我?guī)е麄€(gè)問題回到了現(xiàn)實(shí),只是游沿,這一次回來之后感覺頭腦一片模糊饰抒,知識(shí)量對(duì)于我這種新手來說確實(shí)是大了些,只能在以后的編程路上不斷去琢磨了诀黍。
為了進(jìn)步袋坑,只能不斷地學(xué)習(xí)和總結(jié)!