Android四大組件之Activity

有關(guān)Activity介紹的文字實(shí)在是太多了,本著對(duì)Android開發(fā)基礎(chǔ)知識(shí)進(jìn)行查漏補(bǔ)缺的原則,還是將這部分的知識(shí)梳理成了這篇文章。

Activity作為Android中最為重要的組件,在漢語(yǔ)中似乎一直沒有合適的詞語(yǔ)表達(dá)。Activity是“界面展示”+“后臺(tái)邏輯”的結(jié)合,用“活動(dòng)”一詞對(duì)這一組件進(jìn)行描述實(shí)在是太牽強(qiáng)啦。因此,本文仍然使用Activity來(lái)指代這一組件吧。本文從生命周期和啟動(dòng)模式兩個(gè)部分總結(jié)了Activity相關(guān)的知識(shí)點(diǎn)。


一、 Activity的生命周期

都閃開,首先還是官方文檔中那張熟悉得不能再熟悉的生命周期流程圖:


雖然圖中未列出,Activity在與用戶進(jìn)行交互的過(guò)程中,在如下四種狀態(tài)之間互相切換:

Running: Activity正處于Activity棧最頂端,與用戶正在進(jìn)行交互。(完全可見)

Paused:與Running狀態(tài)不同,Activity此時(shí)未完全顯示出來(lái),例如被一個(gè)dialog或者透明的Activity所部分遮蓋,無(wú)法與用戶交互,但仍然保持著狀態(tài)信息數(shù)據(jù)。(部分可見)

Stopped:當(dāng)Activity被其他Activity完全覆蓋不可見,此時(shí)不再處于Activity棧頂端。(完全不可見)

Destroyed:當(dāng)Activity被系統(tǒng)回收或者被用戶關(guān)閉,則會(huì)被系統(tǒng)銷毀掉。

如圖所示在這四種狀態(tài)的切換過(guò)程中,系統(tǒng)將會(huì)回調(diào)不同的方法:

onCreate():該方法在Activity第一次被創(chuàng)建的時(shí)候被回調(diào),我們通常在該方法中進(jìn)行一些靜態(tài)初始化工作,例如加載頁(yè)面布局,創(chuàng)建View,綁定數(shù)據(jù)等等。

onStart():在Activity被啟動(dòng)或重新啟動(dòng)過(guò)程中會(huì)調(diào)用該方法。

onResume():在Activity能夠與用戶交互之前調(diào)用此方法。我們通常會(huì)在該方法中初始化并打開一些獨(dú)占設(shè)備,例如相機(jī),重新初始化在onPause方法中釋放的資源等。

onPause():當(dāng)系統(tǒng)開始調(diào)用其他Activity時(shí)會(huì)回調(diào)此方法。我們通常會(huì)在其中釋放那些在onResume中打開的資源,確認(rèn)對(duì)持久性數(shù)據(jù)的未保存更改、停止動(dòng)畫、釋放sensor,reciever,ContentProvider保存數(shù)據(jù),以及其他可能消耗 CPU 的內(nèi)容。需要注意的是這里進(jìn)行的操作不能太耗時(shí),因?yàn)樗祷睾?,下一個(gè) Activity 才能繼續(xù)執(zhí)行。該方法與onResume方法相對(duì)應(yīng),這兩對(duì)方法從Activity是否可交互的角度來(lái)回調(diào)的。

onStop():當(dāng)系統(tǒng)要停止或覆蓋該Activity時(shí)會(huì)回調(diào)此方法,此時(shí)Activity已經(jīng)不可見了,該方法與onStart方法相對(duì)應(yīng),這兩對(duì)方法是從Activity是否可見的角度來(lái)回調(diào)的。

onRestart():當(dāng)Activity未被完全銷毀掉,需要重新啟動(dòng)該Activity時(shí)候?qū)?huì)在onStop和onStart方法之間回調(diào)該方法。

onDestroy():當(dāng)系統(tǒng)要銷毀掉Activity前會(huì)調(diào)用該方法。無(wú)論是Activity是人為finish掉還是系統(tǒng)由于資源短缺而回收,都會(huì)回調(diào)該方法。這里可以進(jìn)行一些資源釋放和回收工作。

上述方法的回調(diào)順序都是在Activity處于正常的生命周期內(nèi),而當(dāng)Activity配置發(fā)生改變或系統(tǒng)資源緊張對(duì)Activity進(jìn)行了回收時(shí),Activity則會(huì)被銷毀,抑或重新創(chuàng)建。為了應(yīng)對(duì)Activity非正常生命周期內(nèi)的情況,系統(tǒng)使用了onSaveInstanceState和onRestoreInstanceState兩對(duì)方法來(lái)完成對(duì)Activity狀態(tài)信息和數(shù)據(jù)的存儲(chǔ)和恢復(fù)。這對(duì)方法在Activity正常的生命周期中是不會(huì)被調(diào)用的,只有當(dāng)資源不足或配置改變而導(dǎo)致的異常銷毀重建時(shí)才會(huì)調(diào)用。

在這兩個(gè)方法中,系統(tǒng)自動(dòng)做了一定的存儲(chǔ)和恢復(fù)工作,我們也可以將我們需要保存的數(shù)據(jù)存于Bundle中,從而保證我們Activity的強(qiáng)壯性。


二、 Activity的任務(wù)棧和啟動(dòng)模式

Android系統(tǒng)采用了棧結(jié)構(gòu)來(lái)組織和存儲(chǔ)Activity實(shí)例對(duì)象集合,這樣的棧結(jié)構(gòu)被稱為任務(wù)棧(Task Stack)。一個(gè)任務(wù)棧中的Activity可以來(lái)自不同的App,而同一個(gè)App的不同Activity也可以存在于不同的任務(wù)棧中。棧結(jié)構(gòu)采用FIFO的組織模式,當(dāng)前正與用戶交互的Activity位于棧頂,該任務(wù)棧也位于前臺(tái)。

為了滿足開發(fā)中的各種特殊需求,Activity可以采用四種模式完成啟動(dòng):

standard 默認(rèn)的啟動(dòng)模式。每次都要新創(chuàng)建Activity的實(shí)例對(duì)象,然后進(jìn)入原Activity所在的的任務(wù)棧,覆蓋在原Activity之上。(在這種啟動(dòng)模式下,哪個(gè)Activity啟動(dòng)了新的Activity,那么這個(gè)新的Activity就運(yùn)行在哪個(gè)Activity所在任務(wù)棧中。)

singleTop 棧頂復(fù)用模式。在這種啟動(dòng)模式下,如果當(dāng)前任務(wù)棧頂?shù)腁ctivity與要啟動(dòng)的Activity相同,則不創(chuàng)建新的的Activity對(duì)象(自然也不會(huì)回調(diào)生命周期中的方法),而是復(fù)用當(dāng)前棧頂?shù)腁ctivity對(duì)象,但仍然會(huì)調(diào)用onNewIntent()方法。如果棧頂Activity與要啟動(dòng)的Activity不同,則創(chuàng)建新的Activity實(shí)例對(duì)象,并入棧。這種啟動(dòng)模式通常用于接收消息點(diǎn)擊后所顯示的Activity。

singleTask 棧內(nèi)復(fù)用。在這種啟動(dòng)模式下,系統(tǒng)首先判斷當(dāng)前任務(wù)棧中是否存在要啟動(dòng)的Activity實(shí)例對(duì)象。如果當(dāng)前棧中已經(jīng)存在該Activity實(shí)例對(duì)象,則覆蓋在該Activity實(shí)例對(duì)象之上的Activity都要出棧并銷毀,從而復(fù)用已經(jīng)存在的Activity對(duì)象,但仍然會(huì)調(diào)用onNewIntent()方法。使用該模式時(shí)請(qǐng)注意Activity所要運(yùn)行的任務(wù)棧,該模式具有創(chuàng)建不存在的任務(wù)棧的作用。

另外有一點(diǎn)需要注意的是,當(dāng)所啟動(dòng)的Activity實(shí)例對(duì)象并未位于當(dāng)前任務(wù)棧,而是位于后臺(tái)任務(wù)棧中,則該后臺(tái)任務(wù)棧中的Activity實(shí)例對(duì)象都被切換到前臺(tái)任務(wù)棧中,并仍按原棧中順序組織和存儲(chǔ)。

singleInstance 單例模式。使用該模式啟動(dòng)的Activity,系統(tǒng)為該Activity新建一個(gè)任務(wù)棧來(lái)運(yùn)行,從而可以滿足多個(gè)應(yīng)用共享該Activity實(shí)例的需求。

在Activity實(shí)例對(duì)象的創(chuàng)建和啟動(dòng)過(guò)程中,系統(tǒng)必然要通過(guò)某種方式指定是所啟動(dòng)的Activity實(shí)例對(duì)象,以及該對(duì)象所屬的任務(wù)棧。通常情況下,Activity? A所啟動(dòng)了Activity B,如無(wú)特殊指定,系統(tǒng)會(huì)將B運(yùn)行于A所屬的任務(wù)棧中。

Android系統(tǒng)使用TaskAffinity參數(shù)標(biāo)識(shí)了該Activity對(duì)象期望所屬的任務(wù)棧(默認(rèn)為該app的包名),僅僅是期望,而不是一定要運(yùn)行在該任務(wù)棧中,如果該任務(wù)棧還不存在,未必會(huì)創(chuàng)建該任務(wù)棧(singleTask和singleInstance模式會(huì)創(chuàng)建)。singleTask這種棧內(nèi)復(fù)用模式就是在TaskAffinity所指定的棧內(nèi)進(jìn)行復(fù)用。TaskAffinity參數(shù)通常與allowTaskReparenting結(jié)合使用。

我們可以通過(guò)manifest文件和Intent Flag兩種方式來(lái)指定Activity的啟動(dòng)模式,前者的優(yōu)先級(jí)低于后者。常用的Intent Flag包括以下幾種方式:

Intent.FLAG_ACTIVITY_NEW_TASK:新創(chuàng)建一個(gè)任務(wù)棧來(lái)運(yùn)行Activity,通常用于service啟動(dòng)Activity的場(chǎng)景。

Intent.FLAG_ACTIVITY_SINGLE_TOP:以singleTop模式啟動(dòng)Activity。

Intent.FLAG_ACTIVITY_CLEAR_TOP:通常與Intent.FLAG_ACTIVITY_NEW_TASK相結(jié)合使用,達(dá)到singleTask模式的效果。

Intent.FLAG_ACTIVITY_NO_HISTORY:以該模式啟動(dòng)的Activity,當(dāng)該Activity啟動(dòng)其他Activity后就會(huì)被銷毀掉,不存儲(chǔ)于任務(wù)棧中。

另外,我們還可以在manifest文件中指定clearTaskOnLaunch屬性,保證每次返回該Activity時(shí),其上的Activity都被清除掉,從而保證該Task每次初始化時(shí)都只有這個(gè)一個(gè)Activity。


Note:

良好的編程習(xí)慣:在你負(fù)責(zé)開發(fā)的activity中加入啟動(dòng)該activity的方法。


參考書目:

?Android官方文檔

《Android群英傳》 作者:徐宜生

《Android開發(fā)藝術(shù)探索》 作者:任玉剛

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容