Activity的生命周期與啟動(dòng)模式總結(jié)

一、Activity的生命周期:

1、典型情況下Activity的生命周期(詳見Activity的生命周期的圖):
  • ①onCreate:與onDestory相對(duì)應(yīng),表示Activity正在被創(chuàng)建,這是生命周期的第一個(gè)方法,主要做一些初始化的工作,比如用setContentView去加載布局資源,初始化Activity等。耗時(shí)的工作在異步線程上完成

  • ②onStart:與onStop相對(duì)應(yīng),表示Activity即將開始,這時(shí)的Activity已經(jīng)可見,但是還沒有出現(xiàn)在前臺(tái),還無法與用戶交互。

  • ③onResume:表示Activity已經(jīng)可以看見了,并且出現(xiàn)在前臺(tái),可以與用戶產(chǎn)生交互了。

  • ④onPause:與onResume相對(duì)應(yīng),表示Activity正在暫停,正常情況下,onStop接著就會(huì)被調(diào)用。在特殊情況下,如果這個(gè)時(shí)候用戶快速地再回到當(dāng)前的Activity,那么onResume會(huì)被調(diào)用(極端情況)。一般來說,在這個(gè)生命周期狀態(tài)下,可以做一些存儲(chǔ)數(shù)據(jù)、停止動(dòng)畫的工作,但是不能太耗時(shí),如果是由于啟動(dòng)新的Activity而喚醒的該狀態(tài),那會(huì)影響到新Activity的顯示,原因是onPause必須執(zhí)行完,新的Activity的onResume才會(huì)執(zhí)行。(Activity此時(shí)是可見的:dialog,或者新Activity的主題是透明的)

  • ⑤onStop:表示Activity即將停止,已經(jīng)不可見,同樣不能做過多耗時(shí)操作。

  • ⑥onDestroy:表示Activity即將被銷毀,這是Activity的最后一個(gè)生命周期,可以做一些回收工作和最終的資源釋放。

  • ⑦onRestart:表示Activity正在重新啟動(dòng)。一般情況下,在當(dāng)前Activity從不可見重新變?yōu)榭梢姷臓顟B(tài)時(shí)onRestart就會(huì)被調(diào)用。這種情形一般是由于用戶的行為所導(dǎo)致的,比如用戶按下Home鍵切換到桌面或者打開了一個(gè)新的Activity(這時(shí)當(dāng)前Activity會(huì)暫停,也就是onPause和onStop被執(zhí)行),接著用戶有回到了這個(gè)Activity,就會(huì)出現(xiàn)這種情況。

  • 生命周期圖:

image-20200201165900840.png
2、注意幾點(diǎn):

①當(dāng)用戶按下Back鍵回退時(shí),回調(diào)onPause,onStop,onDestroy

②HOME鍵的執(zhí)行順序:onPause->onStop->onRestart->onStart->onResume BACK鍵的順序: onPause->onStop->onDestroy->(新的Activity)onCreate->onStart->onResume

③在ActivityA啟動(dòng)ActivityB的時(shí)候,需要activityA先執(zhí)行onPause,ActivityB才會(huì)創(chuàng)建(onCreate,onStart,onResume)。

④finish的具體操作:

  • 只是將活動(dòng)推向后臺(tái),將Activity移出棧,并沒有及時(shí)的調(diào)用onDestory()方法,其占用的資源也沒有被及時(shí)釋放

  • 在Activity中的onCreate中調(diào)用finish,則執(zhí)行到的聲明周期方法有:onCreate,onDestroy

  • 在Activity的onStart()中調(diào)用finish()方法,則執(zhí)行的生命周期方法順序?yàn)椋? onCreate() -> onStart() -> onStop() -> onDestroy()

  • 在Activity的onResume()或onPostResume()中調(diào)用finish()方法,則執(zhí)行的生命周期方法順序?yàn)椋? onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDestroy()

⑤Activity的啟動(dòng)過程:簡(jiǎn)單的說就是請(qǐng)求Activity的請(qǐng)求是交給Instrumentation來處理,然后通過Binder向AMS發(fā)送請(qǐng)求,AMS內(nèi)部維護(hù)一個(gè)ActivityStack并負(fù)責(zé)Activity的狀態(tài)同步,AMS通過ActivityThread去同步Activity的狀態(tài)而完成生命周期方法的調(diào)用(有待擴(kuò)充)。

3、異常情況下Activity的生命周期(Activity被系統(tǒng)回收或者由于當(dāng)前設(shè)備的configuration發(fā)生改變從而導(dǎo)致Activity被銷毀重建):
  • 資源相關(guān)的系統(tǒng)配置發(fā)生改變時(shí),Activity被殺死并重新創(chuàng)建(比如:Activity處于豎直狀態(tài),如果突然旋轉(zhuǎn)屏幕,由于系統(tǒng)配置發(fā)生了改變,在默認(rèn)情況下,Activity就會(huì)被銷毀并且重新創(chuàng)建,當(dāng)然可以阻止系統(tǒng)重新創(chuàng)建新的Activity(android:configChanges="orientation|screenSize"),加上screenSize是因?yàn)閙inSdkVersion和targetSdkVersion有一個(gè)大于了13。

  • Activity在異常情況下被終止,系統(tǒng)會(huì)調(diào)用onSaveinstanceState來保存當(dāng)前Activity的狀態(tài),并且調(diào)用時(shí)機(jī)是在onStop之前,與onPause沒有特定的時(shí)序關(guān)系。正常情況下,不會(huì)調(diào)用這個(gè)方法。當(dāng)新Activity被重新創(chuàng)建的時(shí)候,系統(tǒng)會(huì)調(diào)用onRestoreInstanceState來回復(fù)數(shù)據(jù),在onstart之后執(zhí)行onRestoreInstanceState。

  • 資源內(nèi)存不足導(dǎo)致低優(yōu)先級(jí)的Activity被殺死:當(dāng)系統(tǒng)內(nèi)存不足時(shí),系統(tǒng)就會(huì)按照上述優(yōu)先級(jí)去殺死目標(biāo)Activity所在的進(jìn)程,并后續(xù)通過onSaveInstanceState和onRestoreInstanceState來存儲(chǔ)和回復(fù)數(shù)據(jù)。

  • 當(dāng)Activity在異常情況銷毀的時(shí)候,系統(tǒng)會(huì)默認(rèn)保存當(dāng)前Activity的視圖結(jié)構(gòu),并且在Activity重啟的時(shí)候?yàn)槲覀兓謴?fù)這些數(shù)據(jù)(文本框的輸入數(shù)據(jù),ListView的滾動(dòng)位置等)。保存和恢復(fù)View的層次結(jié)構(gòu),系統(tǒng)的工作流程如下:當(dāng)Activity會(huì)調(diào)用onSaveInstanceState去保存數(shù)據(jù),然后委托Window去保存數(shù)據(jù),接著Window再委托它的上級(jí)容器去保存數(shù)據(jù),頂級(jí)是一個(gè)Viewgroup,很可能是一個(gè)DecorView,然后頂級(jí)容器再去一一通知它的子元素去保存數(shù)據(jù)。

二、Activity的啟動(dòng)模式(4種)

1、standard:標(biāo)準(zhǔn)模式
  • 每次啟動(dòng)一個(gè)Activity都會(huì)重新創(chuàng)建一個(gè)新的實(shí)例,不管這個(gè)實(shí)例是否已經(jīng)存在。并且誰啟動(dòng)了這個(gè)Activity,那么這個(gè)Activity就運(yùn)行在啟動(dòng)它的這個(gè)Activity所在的棧中。
    ?
  • 運(yùn)用非Activity的context去啟動(dòng)一個(gè)Activity時(shí)會(huì)出現(xiàn)AndroidRuntimeException異常,主要原因是ApplicationContext沒有所謂的Activity任務(wù)棧,解決辦法是為待啟動(dòng)的Activity指定:FLAG_ACTIVITY_NEW_TASK的標(biāo)記位,此時(shí)相當(dāng)于singleTask的啟動(dòng)模式
2、singleTop:棧頂復(fù)用模式
  • 如果新的Activity已經(jīng)位于任務(wù)棧的棧頂,那么此Activity不會(huì)被重新創(chuàng)建,同時(shí)它的onNewIntent方法會(huì)被調(diào)用,同時(shí)該Activity的onCreate和onStart則不會(huì)被調(diào)用。(注意需要從onNewIntent的intent中獲取新的值,否則用的還是原來intent中的值)
    ?
  • 如果新的Activity已經(jīng)位于任務(wù)棧但不是位于棧頂,或者棧中不存在,則這個(gè)Activity會(huì)被重新創(chuàng)建(oncreate,onStart,onResume)。
3、singleTask:棧內(nèi)復(fù)用模式(單實(shí)例模式)
  • 當(dāng)一個(gè)具有singleTask模式的Activity A 請(qǐng)求啟動(dòng),系統(tǒng)首先會(huì)尋找是否存在A想要的任務(wù)棧(TaskAffinity指定任務(wù)棧的名稱),如果不存在,就先創(chuàng)建一個(gè)A的任務(wù)棧,并將A的實(shí)例放入棧中。
    ?
  • 如果存在A需要的任務(wù)棧,則首先判斷是否存在A的實(shí)例,如果存在,則調(diào)用A的onNewIntent,并將處于A上面的Activity出棧(singleTask自帶clearTop,但是使用標(biāo)志位啟動(dòng)時(shí)需要使用:FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_CLEAR_TOP標(biāo)志位),使得A處于棧頂?shù)奈恢谩? 如果不存在,則創(chuàng)建一個(gè)A的實(shí)例,放置于該棧的棧頂。
4、singleInstance:單實(shí)例模式
  • 具有此模式的Activity只能單獨(dú)的位于一個(gè)任務(wù)棧中。
    ?
  • 比如Activity A 是singleInstance模式,當(dāng)A啟動(dòng)后,系統(tǒng)會(huì)為它創(chuàng)建一個(gè)新的任務(wù)棧。A獨(dú)自運(yùn)行在這個(gè)任務(wù)棧中,后續(xù)的請(qǐng)求均不會(huì)創(chuàng)建新的Activity,除非這個(gè)獨(dú)特的任務(wù)棧被系統(tǒng)銷毀了。

三、TaskAffinity:主要和singleTask啟動(dòng)模式或者allowTaskReparenting屬性配對(duì)使用,其他情況下沒有意義。

  • ①當(dāng)TaskAffinity和singleTask啟動(dòng)模式配對(duì)的時(shí)候,它是具有該模式Activity的目前任務(wù)棧的名字,待啟動(dòng)的Activity會(huì)運(yùn)行在名字和TaskAffinity相同的任務(wù)棧中,Activity默認(rèn)的任務(wù)棧的名稱為包名。
    ?
  • ②當(dāng)TaskAffinity和allowTaskReparenting配對(duì)的時(shí)候,當(dāng)應(yīng)用A啟動(dòng)應(yīng)用B的Activity C后,當(dāng)按下home鍵,再啟動(dòng)應(yīng)用B時(shí),如果Activity的allowTaskReparenting屬性為true,C會(huì)從A的任務(wù)棧轉(zhuǎn)移到B的任務(wù)棧中。

四、如何給Activity指定啟動(dòng)模式:

  • ①在AndroidManifest中指定launchMode.(無法為Activity設(shè)置FLAG_ACTIVITY_CLEAR_TOP標(biāo)識(shí))
    ?
  • ②通過Intent(優(yōu)先級(jí)更高,但是無法指定singleInstance模式):
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

五、Activity常用的Flags

  • ①FLAG_ACTIVITY_NEW_TASK:作用是為Activity指定"singleTask"的啟動(dòng)模式
    ?
  • ②FLAG_ACTIVITY_SINGLE_TOP:作用是為Activity指定"singleTop"的啟動(dòng)模式
    ?
  • ③FLAG_ACTIVITY_CLEAR_TOP:具有此標(biāo)志位的Activity,當(dāng)它啟動(dòng)時(shí),在同一個(gè)任務(wù)棧中所有位于它上面的Activity都要出棧,這個(gè)標(biāo)志位一般會(huì)和singleTask啟動(dòng)模式一起出現(xiàn)。
    ?
  • ④FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:具有這個(gè)標(biāo)志位的Activity不會(huì)出現(xiàn)在歷史Activity的列表中,當(dāng)某些情況,我們不需要通過歷史列表回到我們的Activity的時(shí)候,這個(gè)標(biāo)記比較有用。其等同于:android:excludeFromRecents = "true".

六、顯示Intent和隱式Intent:

  • ①顯示Intent:(指明了要跳到哪個(gè)Activity或者Service,包括包名和類名)
    Intent intent = new Intent(Activity1.this,Activity2.class)
    ?
  • ②隱式Intent:(沒有指明要跳轉(zhuǎn)的類)在AndroidManifest中的intent-filter中實(shí)現(xiàn)過濾。intentFilter的過濾信息有action,category,data.一個(gè)Activity可以有多個(gè)intent-filter,一個(gè)Intent只要能匹配任何一組intent-filter即可成功啟動(dòng)對(duì)應(yīng)的Activity.
    ?
  • ③action的匹配規(guī)則:要求Intent的action存在且必須和過濾規(guī)則中的其中一個(gè)action相同,action區(qū)分大小寫,大小寫不同字符串相同的action會(huì)匹配失效。
    ?
  • ④category的匹配規(guī)則:category的匹配規(guī)則和action不一樣,要求Intent中如果含有category,那么所有的category都必須和過濾規(guī)則中的某個(gè)category相同。(Intent可以不設(shè)置category,但是Intent必須設(shè)置action)
    ?
  • ⑤data的匹配規(guī)則:與action類似,如果Intent中定義了data,那么Intent中必須定義可匹配的data.
    data由兩部分組成,mimeType(媒體類型)和URI(http://www.baidu.com:80/search/info)<shcheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]。
    ?
  • ⑥在隱式Intent跳轉(zhuǎn)的時(shí)候,最好做一下IntentFilter的判斷??词欠裼蠥ctivity可以匹配的IntentFilter.
    • a、采用PackageManager的resolveActivity方法或者Intent的resolveActivity,如果找不到可以匹配的Activity,就返回空。
    • b、PackageManager還提供了queryIntentActivities方法,不是返回最佳匹配的Activity信息,而是返回所有成功匹配的Activity的Activity信息。
最后編輯于
?著作權(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ù)。

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