有關(guān)Activity介紹的文字實(shí)在是太多了诗充,本著對Android開發(fā)基礎(chǔ)知識進(jìn)行查漏補(bǔ)缺的原則疾捍,還是將這部分的知識梳理成了這篇文章。
Activity作為Android中最為重要的組件,在漢語中似乎一直沒有合適的詞語表達(dá)。Activity是“界面展示”+“后臺邏輯”的結(jié)合坯门,用“活動”一詞對這一組件進(jìn)行描述實(shí)在是太牽強(qiáng)啦。因此逗扒,本文仍然使用Activity來指代這一組件吧古戴。本文從生命周期和啟動模式兩個部分總結(jié)了Activity相關(guān)的知識點(diǎn)。
一矩肩、 Activity的生命周期
都閃開现恼,首先還是官方文檔中那張熟悉得不能再熟悉的生命周期流程圖:
雖然圖中未列出,Activity在與用戶進(jìn)行交互的過程中黍檩,在如下四種狀態(tài)之間互相切換:
Running: Activity正處于Activity棧最頂端叉袍,與用戶正在進(jìn)行交互。(完全可見)
Paused:與Running狀態(tài)不同刽酱,Activity此時未完全顯示出來喳逛,例如被一個dialog或者透明的Activity所部分遮蓋,無法與用戶交互棵里,但仍然保持著狀態(tài)信息數(shù)據(jù)润文。(部分可見)
Stopped:當(dāng)Activity被其他Activity完全覆蓋不可見,此時不再處于Activity棧頂端衍慎。(完全不可見)
Destroyed:當(dāng)Activity被系統(tǒng)回收或者被用戶關(guān)閉,則會被系統(tǒng)銷毀掉皮钠。
如圖所示在這四種狀態(tài)的切換過程中稳捆,系統(tǒng)將會回調(diào)不同的方法:
onCreate():該方法在Activity第一次被創(chuàng)建的時候被回調(diào),我們通常在該方法中進(jìn)行一些靜態(tài)初始化工作麦轰,例如加載頁面布局乔夯,創(chuàng)建View砖织,綁定數(shù)據(jù)等等。
onStart():在Activity被啟動或重新啟動過程中會調(diào)用該方法末荐。
onResume():在Activity能夠與用戶交互之前調(diào)用此方法侧纯。我們通常會在該方法中初始化并打開一些獨(dú)占設(shè)備,例如相機(jī)甲脏,重新初始化在onPause方法中釋放的資源等眶熬。
onPause():當(dāng)系統(tǒng)開始調(diào)用其他Activity時會回調(diào)此方法。我們通常會在其中釋放那些在onResume中打開的資源块请,確認(rèn)對持久性數(shù)據(jù)的未保存更改娜氏、停止動畫、釋放sensor墩新,reciever贸弥,ContentProvider保存數(shù)據(jù),以及其他可能消耗 CPU 的內(nèi)容海渊。需要注意的是這里進(jìn)行的操作不能太耗時绵疲,因?yàn)樗祷睾螅乱粋€ Activity 才能繼續(xù)執(zhí)行臣疑。該方法與onResume方法相對應(yīng)盔憨,這兩對方法從Activity是否可交互的角度來回調(diào)的。
onStop():當(dāng)系統(tǒng)要停止或覆蓋該Activity時會回調(diào)此方法朝捆,此時Activity已經(jīng)不可見了般渡,該方法與onStart方法相對應(yīng),這兩對方法是從Activity是否可見的角度來回調(diào)的芙盘。
onRestart():當(dāng)Activity未被完全銷毀掉驯用,需要重新啟動該Activity時候?qū)趏nStop和onStart方法之間回調(diào)該方法。
onDestroy():當(dāng)系統(tǒng)要銷毀掉Activity前會調(diào)用該方法儒老。無論是Activity是人為finish掉還是系統(tǒng)由于資源短缺而回收蝴乔,都會回調(diào)該方法。這里可以進(jìn)行一些資源釋放和回收工作驮樊。
上述方法的回調(diào)順序都是在Activity處于正常的生命周期內(nèi)薇正,而當(dāng)Activity配置發(fā)生改變或系統(tǒng)資源緊張對Activity進(jìn)行了回收時,Activity則會被銷毀囚衔,抑或重新創(chuàng)建挖腰。為了應(yīng)對Activity非正常生命周期內(nèi)的情況,系統(tǒng)使用了onSaveInstanceState和onRestoreInstanceState兩對方法來完成對Activity狀態(tài)信息和數(shù)據(jù)的存儲和恢復(fù)练湿。這對方法在Activity正常的生命周期中是不會被調(diào)用的猴仑,只有當(dāng)資源不足或配置改變而導(dǎo)致的異常銷毀重建時才會調(diào)用。
在這兩個方法中肥哎,系統(tǒng)自動做了一定的存儲和恢復(fù)工作辽俗,我們也可以將我們需要保存的數(shù)據(jù)存于Bundle中疾渣,從而保證我們Activity的強(qiáng)壯性。
二崖飘、 Activity的任務(wù)棧和啟動模式
Android系統(tǒng)采用了棧結(jié)構(gòu)來組織和存儲Activity實(shí)例對象集合榴捡,這樣的棧結(jié)構(gòu)被稱為任務(wù)棧(Task Stack)。一個任務(wù)棧中的Activity可以來自不同的App朱浴,而同一個App的不同Activity也可以存在于不同的任務(wù)棧中吊圾。棧結(jié)構(gòu)采用FIFO的組織模式,當(dāng)前正與用戶交互的Activity位于棧頂赊琳,該任務(wù)棧也位于前臺街夭。
為了滿足開發(fā)中的各種特殊需求,Activity可以采用四種模式完成啟動:
standard 默認(rèn)的啟動模式躏筏。每次都要新創(chuàng)建Activity的實(shí)例對象板丽,然后進(jìn)入原Activity所在的的任務(wù)棧,覆蓋在原Activity之上趁尼。(在這種啟動模式下埃碱,哪個Activity啟動了新的Activity,那么這個新的Activity就運(yùn)行在哪個Activity所在任務(wù)棧中酥泞。)
singleTop 棧頂復(fù)用模式砚殿。在這種啟動模式下,如果當(dāng)前任務(wù)棧頂?shù)腁ctivity與要啟動的Activity相同芝囤,則不創(chuàng)建新的的Activity對象(自然也不會回調(diào)生命周期中的方法)似炎,而是復(fù)用當(dāng)前棧頂?shù)腁ctivity對象,但仍然會調(diào)用onNewIntent()方法悯姊。如果棧頂Activity與要啟動的Activity不同羡藐,則創(chuàng)建新的Activity實(shí)例對象,并入棧悯许。這種啟動模式通常用于接收消息點(diǎn)擊后所顯示的Activity仆嗦。
singleTask 棧內(nèi)復(fù)用。在這種啟動模式下先壕,系統(tǒng)首先判斷當(dāng)前任務(wù)棧中是否存在要啟動的Activity實(shí)例對象瘩扼。如果當(dāng)前棧中已經(jīng)存在該Activity實(shí)例對象,則覆蓋在該Activity實(shí)例對象之上的Activity都要出棧并銷毀垃僚,從而復(fù)用已經(jīng)存在的Activity對象集绰,但仍然會調(diào)用onNewIntent()方法。使用該模式時請注意Activity所要運(yùn)行的任務(wù)棧谆棺,該模式具有創(chuàng)建不存在的任務(wù)棧的作用栽燕。
另外有一點(diǎn)需要注意的是,當(dāng)所啟動的Activity實(shí)例對象并未位于當(dāng)前任務(wù)棧,而是位于后臺任務(wù)棧中纫谅,則該后臺任務(wù)棧中的Activity實(shí)例對象都被切換到前臺任務(wù)棧中,并仍按原棧中順序組織和存儲溅固。
singleInstance 單例模式付秕。使用該模式啟動的Activity,系統(tǒng)為該Activity新建一個任務(wù)棧來運(yùn)行侍郭,從而可以滿足多個應(yīng)用共享該Activity實(shí)例的需求询吴。
在Activity實(shí)例對象的創(chuàng)建和啟動過程中,系統(tǒng)必然要通過某種方式指定是所啟動的Activity實(shí)例對象亮元,以及該對象所屬的任務(wù)棧猛计。通常情況下,Activity? A所啟動了Activity B爆捞,如無特殊指定奉瘤,系統(tǒng)會將B運(yùn)行于A所屬的任務(wù)棧中。
Android系統(tǒng)使用TaskAffinity參數(shù)標(biāo)識了該Activity對象期望所屬的任務(wù)棧(默認(rèn)為該app的包名)煮甥,僅僅是期望盗温,而不是一定要運(yùn)行在該任務(wù)棧中,如果該任務(wù)棧還不存在成肘,未必會創(chuàng)建該任務(wù)棧(singleTask和singleInstance模式會創(chuàng)建)卖局。singleTask這種棧內(nèi)復(fù)用模式就是在TaskAffinity所指定的棧內(nèi)進(jìn)行復(fù)用。TaskAffinity參數(shù)通常與allowTaskReparenting結(jié)合使用双霍。
我們可以通過manifest文件和Intent Flag兩種方式來指定Activity的啟動模式砚偶,前者的優(yōu)先級低于后者。常用的Intent Flag包括以下幾種方式:
Intent.FLAG_ACTIVITY_NEW_TASK:新創(chuàng)建一個任務(wù)棧來運(yùn)行Activity洒闸,通常用于service啟動Activity的場景染坯。
Intent.FLAG_ACTIVITY_SINGLE_TOP:以singleTop模式啟動Activity。
Intent.FLAG_ACTIVITY_CLEAR_TOP:通常與Intent.FLAG_ACTIVITY_NEW_TASK相結(jié)合使用顷蟀,達(dá)到singleTask模式的效果酒请。
Intent.FLAG_ACTIVITY_NO_HISTORY:以該模式啟動的Activity,當(dāng)該Activity啟動其他Activity后就會被銷毀掉鸣个,不存儲于任務(wù)棧中羞反。
另外,我們還可以在manifest文件中指定clearTaskOnLaunch屬性囤萤,保證每次返回該Activity時昼窗,其上的Activity都被清除掉,從而保證該Task每次初始化時都只有這個一個Activity涛舍。
Note:
良好的編程習(xí)慣:在你負(fù)責(zé)開發(fā)的activity中加入啟動該activity的方法澄惊。
參考書目:
?Android官方文檔
《Android群英傳》 作者:徐宜生
《Android開發(fā)藝術(shù)探索》 作者:任玉剛