日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

深入Android 【五】 —— 任務(wù)和進(jìn)程

 My鏡像站 2011-11-16
關(guān)于Android中的組件和應(yīng)用,之前涉及,大都是靜態(tài)的概念。而當(dāng)一個應(yīng)用運(yùn)行起來,就難免會需要關(guān)心進(jìn)程、線程這樣的概念。在Android中,組件的動態(tài)運(yùn)行,有一個最與眾不同的概念,就是Task,翻譯成任務(wù),應(yīng)該還是比較順理成章的。
Task的介入,最主要的作用,是將組件之間的連接,從進(jìn)程概念的細(xì)節(jié)中剝離出來,可以以一種不同模型的東西進(jìn)行配置,在很多時候,能夠簡化上層開發(fā)人員的理解難度,幫助大家更好的進(jìn)行開發(fā)和配置。

任務(wù)

在SDK中關(guān)于Taskguide/topics/fundamentals.html#acttask),有一個很好的比方,說,Task就相當(dāng)于應(yīng)用(application)的概念。在開發(fā)人員眼中,開發(fā)一個Android程序,是做一個個獨(dú)門獨(dú)戶的組件,但對于一般用戶而言,它們感知到的,只是一個運(yùn)行起來的整體應(yīng)用,這個整體背后,就是Task。
Task,簡單的說,就是一組以棧的模式聚集在一起的Activity組件集合。 它們有潛在的前后驅(qū)關(guān)聯(lián),新加入的Activity組件,位于棧頂,并僅有在棧頂?shù)腁ctivity,才會有機(jī)會與用戶進(jìn)行交互。而當(dāng)棧頂?shù)? Activity完成使命退出的時候,Task會將其退棧,并讓下一個將跑到棧頂?shù)腁ctivity來于用戶面對面,直至棧中再無更多 Activity,Task結(jié)束。

事件Task棧(粗體為棧頂組件)
點(diǎn)開Email應(yīng)用,進(jìn)入收件箱(Activity A)A
選中一封郵件,點(diǎn)擊查看詳情(Activity B)AB
點(diǎn)擊回復(fù),開始寫新郵件(Activity C)ABC
寫了幾行字,點(diǎn)擊選擇聯(lián)系人,進(jìn)入選擇聯(lián)系人界面(Activity D)ABCD
選擇好了聯(lián)系人,繼續(xù)寫郵件ABC
寫好郵件,發(fā)送完成,回到原始郵件AB
點(diǎn)擊返回,回到收件箱A
退出Email程序null

如 上表所示,是一個實(shí)例。從用戶從進(jìn)入郵箱開始,到回復(fù)完成,退出應(yīng)用整個過程的Task棧變化。這是一個標(biāo)準(zhǔn)的棧模式,對于大部分的狀況,這樣的Task 模型,足以應(yīng)付,但是,涉及到實(shí)際的性能、開銷等問題,就會變得殘酷許多。比如,啟動一個瀏覽器,在Android中是一個比較沉重的過程,它需要做很多 初始化的工作,并且會有不小的內(nèi)存開銷。但與此同時,用瀏覽器打開一些內(nèi)容,又是一般應(yīng)用都會有的一個需求。設(shè)想一下,如果同時有十個運(yùn)行著的應(yīng)用(就會 對應(yīng)著是多個Task),都需要啟動瀏覽器,這將是一個多么殘酷的場面,十個Task棧都堆積著很雷同的瀏覽器Activity,是多么華麗的一種浪費(fèi) 啊。于是你會有這樣一種設(shè)想,瀏覽器Activity,可不可以作為一個單獨(dú)的Task而存在,不管是來自那個Task的請求,瀏覽器的Task,都不會 歸并過去。這樣,雖然瀏覽器Activity本身需要維系的狀態(tài)更多了,但整體的開銷將大大的減少,這種舍小家為大家的行為,還是很值得歌頌的。
如此值得歌頌的行為,Android當(dāng)然會舉雙手支持的。在Android中,每一個Activity的Task模式,都是可以由Activity提供方(通過配置文件...)和Activity使用方(通過Intent中的flag信息...)進(jìn)行配置和選擇。當(dāng)然,使用方對Activity的控制力,是限定在提供方允許的范疇內(nèi)進(jìn)行,提供方明令禁止的模式,使用方是不能夠越界使用的。
在SDK中(guide/topics/fundamentals.html#acttask),將兩者實(shí)現(xiàn)Task模式配置的方式,寫的非常清晰了,我再很絮叨挑選一些來解釋一下(完整可配置項(xiàng),一定要看SDK,下面只是其中常用的若干項(xiàng)...)。提供方對組件的配置,是通過配置文件(Manifest)<activity>項(xiàng)來進(jìn)行的,而調(diào)用方,則是通過Intent對象的flag進(jìn)行抉擇的。相對于標(biāo)準(zhǔn)的Task棧的模式,配置的主要方向有兩個:一則是破壞已有棧的進(jìn)出規(guī)則,或樣式;另一則是開辟新Task棧完成本應(yīng)在同一Task棧中完成的任務(wù)。
對于應(yīng)用開發(fā)人員而言,<activity>中的launchMode屬性,是需要經(jīng)常打交道的。它有四種模式:"standard", "singleTop", "singleTask", "singleInstance"。
standard模式, 是默認(rèn)的也是標(biāo)準(zhǔn)的Task模式,在沒有其他因素的影響下,使用此模式的Activity,會構(gòu)造一個Activity的實(shí)例,加入到調(diào)用者的Task棧 中去,對于使用頻度一般開銷一般什么都一般的Activity而言,standard模式無疑是最合適的,因?yàn)樗壿嫼唵螚l理清晰,所以是默認(rèn)的選擇。
singleTop模式,基本上于standard一致,僅在請求的Activity正好位于棧頂時,有所區(qū)別。此時,配置成singleTop的Activity,不再會構(gòu)造新的實(shí)例加入到Task棧中,而是將新來的Intent發(fā)送到棧頂Activity中,棧頂?shù)腁ctivity可以通過重載onNewIntent來 處理新的Intent(當(dāng)然,也可以無視...)。這個模式,降低了位于棧頂時的一些重復(fù)開銷,更避免了一些奇異的行為(想象一下,如果在棧頂連續(xù)幾個都 是同樣的Activity,再一級級退出的時候,這是怎么樣的用戶體驗(yàn)...),很適合一些會有更新的列表Activity展示。一個活生生的實(shí)例是,在 Android默認(rèn)提供的應(yīng)用中,瀏覽器(Browser)的書簽Activity(BrowserBookmarkPage),就用的是singleTop。
singleTop模式,雖然破壞了原有棧的邏輯(復(fù)用了棧頂,而沒有構(gòu)造新元素進(jìn)棧...),但并未開辟專屬的Task。而singleTask,和singleInstance,則都采取的另辟Task的蹊徑。標(biāo)志為singleTask的Activity,最多僅有一個實(shí)例存在,并且,位于以它為根的Task中。 所有對該Activity的請求,都會跳到該Activity的Task中展開進(jìn)行。singleTask,很象概念中的單件模式,所有的修改都是基于一 個實(shí)例,這通常用在構(gòu)造成本很大,但切換成本較小的Activity中。在Android源碼提供的應(yīng)用中,該模式被廣泛的采用,最典型的例子,還是瀏覽 器應(yīng)用的主Activity(名為Browser...),它是展示當(dāng)前tab,當(dāng)前頁面內(nèi)容的窗口。它的構(gòu)造成本大,但頁面的切換還是較快的,于 singleTask相配,還是挺天作之合的。
相比之下,singleInstance顯得更為極端一些。在大部分時候singleInstance與singleTask完全一致,唯一的不同在于,singleInstance的Activity,是它所在棧中僅有的一個Activity, 如果涉及到的其他Activity,都移交到其他Task中進(jìn)行。這使得singleInstance的Activity,像一座孤島,徹底的黑盒,它不 關(guān)注請求來自何方,也不計(jì)較后續(xù)由誰執(zhí)行。在Android默認(rèn)的各個應(yīng)用中,很少有這樣的Activity,在我個人的工程實(shí)踐中,曾嘗試在有道詞典快速取詞Activity中采用過,是因?yàn)槲矣X得快速取詞入口足夠方便(從notification中點(diǎn)選進(jìn)入),并且會在各個場合使用,應(yīng)該做得完全獨(dú)立。
除了launchMode可以用來調(diào)配Task,<activity>的另一屬性taskAffinity,也是常常被使用。taskAffinity,是一種物以類聚的思想,它傾向于將taskAffinity屬性相同的Activity,扔進(jìn)同一個Task中。不過,它的約束力,較之launchMode而言,弱了許多。只有當(dāng)<activity>中的allowTaskReparen ting設(shè)置為true,抑或是調(diào)用方將Intent的flag添加FLAG_ACTIVITY_NEW_TASK屬 性時才會生效。如果有機(jī)會用到Android的Notification機(jī)制就能夠知道,每一個由notification進(jìn)行觸發(fā)的Activity, 都必須是一個設(shè)成FLAG_ACTIVITY_NEW_TASK的Intent來調(diào)用。這時候,開發(fā)者很可能需要妥善配置taskAffinity屬性, 使得調(diào)用起來的Activity,能夠找到組織,在同一taskAffinity的Task中進(jìn)行運(yùn)行。

進(jìn)程

在 大多數(shù)其他平臺的開發(fā)中,每個開發(fā)人員對自己應(yīng)用的進(jìn)程模型都有非常清晰的了解。比如,一個控制臺程序,你可以想見它從main函數(shù)開始啟動一個進(jìn)程,到 main函數(shù)結(jié)束,進(jìn)程執(zhí)行完成退出;在UI程序中,往往是有一個消息循環(huán)在跑,當(dāng)接受到Exit消息后,退出消息循環(huán)結(jié)束進(jìn)程。在該程序運(yùn)行過程中,啟 動了什么進(jìn)程,和第三方進(jìn)程進(jìn)行通信等等操作,每個開發(fā)者都是心如明鏡一本帳算得清清楚楚。進(jìn)程邊界,在這里,猶如國界一般,每一次穿越都會留下深深的印 跡。
在Android程序中,開發(fā)人員可以直接感知的,往往是Task而已。倍感清晰的,是組件邊界,而進(jìn)程邊界變得難以琢磨,甚至有了進(jìn)程托管一說。Android中不但剝奪了手工鍛造內(nèi)存權(quán)力,連手工處置進(jìn)程的權(quán)責(zé),也毫不猶豫的獨(dú)占了。
當(dāng)然,Android隱藏進(jìn)程細(xì)節(jié),并不是刻意為之,而是自然而然水到渠成的。如果,我們把傳統(tǒng)的應(yīng)用稱為面向進(jìn)程的開發(fā),那么,在Android中,我們做得就是面向組件的開發(fā)。從前面的內(nèi)容可以知道,Android組件間的跳轉(zhuǎn)和通信,都是在第三方介入的 前提下進(jìn)行,正由于這種介入,使得兩個組件一般不會直接發(fā)生聯(lián)系(于Service的通信,是不需要第三方介入的,因此Android把它全部假設(shè)成為穿 越進(jìn)程邊界,統(tǒng)一基于RPC來通信,這樣,也是為了掩蓋進(jìn)程細(xì)節(jié)...),其中是否穿越進(jìn)程邊界也就變得不重要。因此,如果這時候,還需要開發(fā)者關(guān)注進(jìn) 程,就會變得很奇怪,很費(fèi)解,干脆,Android將所有的進(jìn)程一并托管去了,上層無須知道進(jìn)程的生死和通信細(xì)節(jié)。
在Android的底層,進(jìn)程構(gòu)造了底部的一個運(yùn)行池,不僅僅是Task中的各個Activity組件,其他三大組件Service、Content Provider、Broadcast Receiver,都是寄宿在底層某個進(jìn)程中,進(jìn)行運(yùn)轉(zhuǎn)。在這里,進(jìn)程更像一個資源池(概念形如線程池,上層要用的時候取一個出來就好,而不關(guān)注具體取了哪一個...),只是為了承載各個組件的運(yùn)行,而各個組件直接的邏輯關(guān)系,它們并不關(guān)心。但我們可以想象,為了保證整體性,在默認(rèn)情況下,Android肯定傾向于將同一Task、同一應(yīng)用的各個組件扔進(jìn)同一個進(jìn)程內(nèi),但是當(dāng)然,出于效率考慮,Android也是允許開發(fā)者進(jìn)行配置。
在Android中,整體的<application>(將影響其中各個組件...)和底下各個組件,都可以設(shè)置<process>屬性,相同<process>屬性的組件將扔到同一個進(jìn)程中運(yùn)行。最常見的使用場景,是通過配置<application>的process屬性,將不同的相關(guān)應(yīng)用,塞進(jìn)一個進(jìn)程,使得它們可以同生共死。還有就是將經(jīng)常和某個Service組件進(jìn)行通信的組件,放入同一個進(jìn)程,因?yàn)榕cService通信是個密集操作,走的是RPC,開銷不小,通過配置,可以變成進(jìn)程內(nèi)的直接引用,消耗頗小。
除了通過<process>屬性,不同的組件還有一些特殊的配置項(xiàng),以Content Provider為例(通過<provider>項(xiàng)進(jìn)行配置...)。<provider>項(xiàng)有一個mutiprocess的屬性,默認(rèn)值為false,這意味著Content Provider,僅會在提供該組件的應(yīng)用所在進(jìn)程構(gòu)造一個實(shí)例, 第三方想使用就需要經(jīng)由RPC傳輸數(shù)據(jù)。這種模式,對于構(gòu)造開銷大,數(shù)據(jù)傳輸開銷小的場合是非常適用的,并且可能提高緩存的效果。但是,如果是數(shù)據(jù)傳輸很 大,抑或是希望在此提高傳輸?shù)男?,就需要將mutiprocess設(shè)置成true,這樣,Content Provider就會在每一個調(diào)用它的進(jìn)程中構(gòu)造一個實(shí)例,避免進(jìn)程通信的開銷。
既然,是Android系統(tǒng)幫助開發(fā)人員托管了進(jìn)程,那么就需要有一整套紛繁的算法去執(zhí)行回收邏輯。Android中各個進(jìn)程的生死,和運(yùn)行在其中的各個組件有著密切的聯(lián)系,進(jìn)程們依照其上組件的特點(diǎn),被排入一個優(yōu)先級體系,在需要回收時,從低優(yōu)先級到高優(yōu)先級回收。Android進(jìn)程共分為五類優(yōu)先級,分別是:Foreground ProcessVisible ProcessService ProcessBackground ProcessEmpty Process。顧名思義不難看出,這說明,越和用戶操作緊密相連的,越是正與用戶交互的,優(yōu)先級越高,越難被回收。具體詳情,參見:guide/topics/fundamentals.html#proclife。
有了優(yōu)先級,還需要有良好的回收時機(jī)。回收太早,緩存命中概率低可能引起不斷的創(chuàng)造進(jìn)程銷毀進(jìn)程,池的優(yōu)勢蕩然無存;回收的太晚,整體開銷大,系統(tǒng)運(yùn)行效率降低,好端端的法拉利可能被糟蹋成一枚QQ老爺車。Android的進(jìn)程回收,最重要的是考量內(nèi)存開銷,以及電量等其他資源狀況,此外每個進(jìn)程承載的組件數(shù)量、單個應(yīng)用開辟的進(jìn)程數(shù)量等數(shù)量指標(biāo),也是作為衡量的一個重要標(biāo)識。另外,一些運(yùn)行時的時間開銷,也被嚴(yán)格監(jiān)控,啟動慢的進(jìn)程會很被強(qiáng)行kill掉。Android會定時檢查上述參數(shù),也會在一些很可能發(fā)生進(jìn)程回收的時間點(diǎn),比如某個組件執(zhí)行完成后,來做回收的嘗試。
從 用戶體驗(yàn)角度來看,Android的進(jìn)程機(jī)制,會有很可喜的一面,有的程序啟動速度很慢,但是在資源充沛的前提下,你反復(fù)的退出再使用,則啟動變得極其快 速(進(jìn)程沒死,只是從后臺弄到了前臺),這就是拜進(jìn)程托管所賜的。當(dāng)然,可喜的另一面就是可悲了,Android的托管算法,還時不時的展現(xiàn)其幼稚的一 面,明明用戶已經(jīng)明顯感覺到操作系統(tǒng)運(yùn)行速度下降了,打開任務(wù)管理器一看,一票應(yīng)用還生龍活虎的跳躍著,必須要手動幫助它們終結(jié)生命找到墳?zāi)?,這使得任務(wù) 管理器基本成為Android的裝機(jī)必備軟件。
從 開發(fā)角度上來看,Android這套進(jìn)程機(jī)制,解放了開發(fā)者的手腳。開發(fā)人員不需要處心積慮的構(gòu)造一個后臺進(jìn)程偷偷默默監(jiān)聽某個時間,并嘗試用各種各樣的 守護(hù)手段,把自己的進(jìn)程鍛造的猶如不死鳥一輝一般,進(jìn)程生死的問題,已經(jīng)原理了普通開發(fā)人員需要管理的范疇內(nèi)。但同時,于GC和人肉內(nèi)存管理的爭議一樣, 所有開發(fā)人員都不相信算法能比自己做得效率更高更出色。但我一直堅(jiān)信一點(diǎn),所有效率的優(yōu)勢都會隨著算法的不斷改良硬件的不斷提升而消失殆盡,只有開發(fā)模式的簡潔不會隨時間而有任何變化。

組件生命周期

任 何架構(gòu)上的變化,都會引起上層開發(fā)模式的變化,Android的進(jìn)程模型,雖然使開發(fā)者不再需要密切關(guān)注進(jìn)程的創(chuàng)建和銷毀的時機(jī),但仍然需要關(guān)注這些時間 點(diǎn)對組件的影響。比如,你可能需要在進(jìn)程銷毀之前,將寫到內(nèi)存上的內(nèi)容,持久化到硬盤上,這就需要關(guān)注進(jìn)程退出前發(fā)生的一些事件。
在Android中,把握這些時間點(diǎn),就必須了解組件生命周期Components Lifecycles)。所謂組件的生命在周期,就是在組件在前后臺切換、被用戶創(chuàng)建退出、被系統(tǒng)回收等等事件發(fā)生的時候,會有一些事件通知到對應(yīng)組件上,開發(fā)人員可以選擇性的處理這些事件在對應(yīng)的時間點(diǎn)上來完成一些附加工作。
除Content Provider,其他組件都會有生命周期的概念,都需要依照這個模型定時定點(diǎn)處理一些狀況,全部內(nèi)容參見:guide/topics/fundamentals.html#lcycles。在這里,擒賊先擒王,還是拿Activity出來作楷模。



繼續(xù)偷圖,來自SDK。一個自然的Activity生命旅途,從onCreate開始,到onDestroy消亡。但月有陰晴圓缺組件有禍福旦夕,在系統(tǒng)需要的時候且組件位于后臺時,所在的進(jìn)程隨時可能為國捐軀被回收,這就使得知道切入后臺這個事情也變得很重要。
當(dāng)組件進(jìn)入棧頂,與用戶開始交互,會調(diào)用onResume函數(shù),類似,當(dāng)退出棧頂,會有onPause函 數(shù)被呼喚。onResume和onPause可以處理很多事情,最常規(guī)的,就是做一些文件或設(shè)置項(xiàng)的讀寫工作。因?yàn)?,在該組件不再前臺運(yùn)行的時候,可能別 的組件會需要讀寫同樣一份文件和設(shè)置,如果不再onResume做刷新工作,用的可能就是一份臟數(shù)據(jù)了(當(dāng)然,具體情況,還需要具體分析,如果文件不會被 多頭讀寫,可以放到onCreate里面去做讀工作)。
除了前述切入后臺會被其他組件騷擾的問題,另外,死無定因也是件很可怕的事情。在Android中,組件都有兩種常見的死法,一種是自然消亡,比如,棧元素ABC,變成AB了,C組件就自然消亡了。這種死發(fā)輕如鴻毛,不需要額外關(guān)心。但另一種情況,就是被系統(tǒng)回收,那是死的重如泰山,為國捐軀嘛。
但 這種捐軀的死法,對用戶來說,比較費(fèi)解。想象一下,一款游戲,不能存盤,你一直玩啊玩,三天三夜沒合眼,這時候你mm打來電話鼓勵一下,你精神抖擻的準(zhǔn)備 再接再厲,卻發(fā)現(xiàn)你的游戲進(jìn)程,在切入后臺之后,被系統(tǒng)回收了,一夜回到解放前三天努力成為一場泡影,你會不會想殺做游戲的人,會不會會不會會不會,一定 會嘛。這時候,如果沒有Activity生命周期這碼事,游戲程序員一定是被冤死的,成了Android的替罪羊。但是,Android的組件是有生命周 期的,如果真的發(fā)生這樣情況,不要猶豫,去殺開發(fā)的程序員吧。
為了逃生,程序員們有一塊免死金牌,那就是Android的state機(jī)制。所謂state,就是開發(fā)人員將一些當(dāng)前運(yùn)行的狀態(tài)信息存放在一個Bundle對象里面,這是一個可序列化鍵值對集合。如果該Activity組件所處的進(jìn)程需要回收,Android核心會將其上Activity組件的Bundle對象持久化到磁盤上,當(dāng)用戶回到該Activity時候,系統(tǒng)會重新構(gòu)造該組件,并將持久化到磁盤上的Bundle對象恢復(fù)。有了這樣的持久化的狀態(tài)信息,開發(fā)人員可以很好的區(qū)分具體死法,并有機(jī)會的使得死而復(fù)生的Activity恢復(fù)到死前狀態(tài)。開發(fā)者應(yīng)該做的,是通過onSaveInstanceState函數(shù)把需要維系的狀態(tài)信息(在默認(rèn)的狀態(tài)下,系統(tǒng)控件都會自己保存相關(guān)的狀態(tài)信息,比如TextView,會保存當(dāng)前的Text信息,這都不需要開發(fā)人員擔(dān)心...),寫入到Bundle對象,然后在onRestoreInstanceState函數(shù)中讀取并恢復(fù)相關(guān)信息(onCreate,onStart,也都可以處理...)。

線程

讀取數(shù)據(jù),后臺處理,這些猥瑣的伙計(jì),自然少不了線程的參與。在Android核心的調(diào)度層面,是不屑于考量線程的,它關(guān)注的只有進(jìn)程,每一個組件的構(gòu)造和處理,都是在進(jìn)程的主線程上做的,這樣可以保證邏輯的足夠簡單。多線程,往往都是開發(fā)人員需要做的。
Android的線程,也是通過派生Java的Thread對象,實(shí)現(xiàn)Run方法來實(shí)現(xiàn)的。但當(dāng)用戶需要跑一個具有消息循環(huán)的線程的時候,Android有更好的支持,來自于HandlerLooper。Handler做的是消息的傳送和分發(fā),派生其handleMessage函數(shù),可以處理各種收到的消息,和win開發(fā)無異。Looper的任務(wù),則是構(gòu)造循環(huán),等候退出或其他消息的來臨。在Looper的SDK頁面,有一個消息循環(huán)線程實(shí)現(xiàn)的標(biāo)準(zhǔn)范例,當(dāng)然,更為標(biāo)準(zhǔn)的方式也許是構(gòu)造一個HandlerThread線程,將它的Looper傳遞給Handler。
在Android中,Content Provider的使用,往往和線程掛鉤,誰讓它和數(shù)據(jù)相關(guān)呢。在前面提到過,Content Provider為了保持更多的靈活性,本身只提供了同步調(diào)用的接口,而由于異步對Content Provider進(jìn)行增刪改查是一個常做操作,Android通過AsyncQueryHandler對象,提供了異步接口。這是一個Handler的子類,開發(fā)人員可以調(diào)用startXXX方法發(fā)起操作,通過派生onXXXComplete方法,等待執(zhí)行完畢后的回調(diào),從而完成整個異步調(diào)用的流程,十分的簡約明了。

實(shí)現(xiàn)

整個任務(wù)、進(jìn)程管理的核心實(shí)現(xiàn),盡在ActivityManagerService中。上一篇說到,Intent解析,就是這個ActivityManagerService來負(fù)責(zé)的,其實(shí),它是一個很名不副實(shí)的類,因?yàn)殡m然名為Activity的Manager Service,但它管轄的范圍,不只是Activity,還有其他三類組件,和它們所在的進(jìn)程。
在ActivityManagerService中,有兩類數(shù)據(jù)結(jié)構(gòu)最為醒目,一個是ArrayList,另一個是HashMap。 ActivityManagerService有大量的ArrayList,每一個組件,會有多個ArrayList來分狀態(tài)存放。調(diào)度工作,往往就是從 一個ArrayList里面拿出來,找個方法調(diào)一調(diào),然后扔到另一個ArrayList里面去,當(dāng)這個組件沒對應(yīng)的ArrayList放著的時候,說明它 離死不遠(yuǎn)了。HashMap,是因?yàn)橛薪M件是需要用名字或Intent信息做定位的,比如Content Provider,它的查找,都是依據(jù)Uri,有了HashMap,一切都順理成章了。
ActivityManagerService用一些名曰xxxRecord的數(shù)據(jù)結(jié)構(gòu),來表達(dá)各個存活的組件。于是就有了,HistoryRecord(保存Activity信息的,之所以叫History,是相對Task棧而言的...),ServiceRecordBroadcastRecord,ContentProviderRecord,TaskRecord,ProcessRecord,等等。
值 得注意的,是TaskRecord,我們一直再說,Task棧這樣的概念,其實(shí),真實(shí)的底層,并不會在TaskRecord中,維系一個Activity 的棧。在ActivityManagerService中,各個任務(wù)的Activity,都以HistoryRecord的形式,集中存放在一個 ArrayList中,每個HistoryRecord,會存放它所在TaskRecord的引用。當(dāng)有一個Activity,執(zhí)行完成,從概念上的 Task棧中退出,Android是通過從當(dāng)前HistoryRecord位置往前掃描同一個TaskRecord的HistoryRecord來完成 的。這個設(shè)計(jì),使得上層很多看上去邏輯很復(fù)雜的Task體系,在實(shí)現(xiàn)變得很統(tǒng)一而簡明,值得稱道。
ProcessRecord,是整個進(jìn)程托管實(shí)現(xiàn)的核心,它存放有運(yùn)行在這個進(jìn)程上,所有組件的信息,根據(jù)這些信息,系統(tǒng)有一整套的算法來決議如何處置這個進(jìn)程,如果對回收算法感興趣,可以從ActivityManagerService的trimApplications函數(shù)入手來看。
對于開發(fā)者來說,去了解這部分實(shí)現(xiàn),主要是可以幫助理解整個進(jìn)程和任務(wù)的概念,如果覺得這塊理解的清晰了,就不用去碰ActivityManagerService這個龐然大物了。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多