1,生命周期
正常情況系,Activity會經(jīng)歷如下幾個階段:
onCreate:表示Activity正在被創(chuàng)建坤学。
onRestart:表示Activity正在被重新啟動疯坤。
onStart:表示Activity正在被啟動,這時已經(jīng)可見深浮,但沒有出現(xiàn)在前臺無法進行交互压怠。
onResume:表示Activity已經(jīng)可見,并且處于前臺飞苇。
onPause:表示Activity正在停止(可做一次保存狀態(tài)停止動畫等非耗時操作)菌瘫。
onStop:表示Activity即將停止(可進行重量級回收工作)。
onDestroy:表示Activity即將被銷毀布卡。
onRestart:表示activity重新啟動
對于生命周期:
第一次啟動:onCreate->onStart->onResume雨让;
打開新的Activity或者返回桌面:onPause->onStop。如果打開新的Activity為透明主題忿等,則不會調(diào)用onStop栖忠;
當回到原來Activity時:onRestart->onStart->onResume;
當按下返回鍵:onPause->onStop->onDestroy
2,啟動模式
一贸街、在將啟動模式之前必須了解的一些知識:
? ? 在正式的介紹Activity的啟動模式之前庵寞,我們首先要了解一些旁邊的知識,這些知識如果說模糊不清薛匪,那么在討論啟動模式的時候會一頭霧水捐川。
1.一個應用程序通常會有多個Activity,這些Activity都有一個對應的action(如MainActivity的action)逸尖,我們可以通過action來啟動對應Activity(隱式啟動)古沥。
<action android:name="android.intent.action.MAIN" />
2.一個應用程序可以說由一系列組件組成,這些組件以進程為載體娇跟,相互協(xié)作實現(xiàn)App功能岩齿。
3.任務棧(Task Stack)或者叫退回棧(Back Stack)介紹:
3.1.任務棧用來存放用戶開啟的Activity。
3.2.在應用程序創(chuàng)建之初逞频,系統(tǒng)會默認分配給其一個任務棧(默認一個)纯衍,并存儲根Activity。
3.3.同一個Task Stack苗胀,只要不在棧頂襟诸,就是onStop狀態(tài):
3.4.任務棧的id自增長型,是Integer類型基协。
3.5.新創(chuàng)建Activity會被壓入棧頂歌亲。點擊back會將棧頂Activity彈出,并產(chǎn)生新的棧頂元素作為顯示界面(onResume狀態(tài))澜驮。
3.6.當Task最后一個Activity被銷毀時陷揪,對應的應用程序被關閉,清除Task棧,但是還會保留應用程序進程(狂點Back退出到Home界面后點擊Menu會發(fā)現(xiàn)還有這個App的框框悍缠。個人理解應該是這個意思)卦绣,再次點擊進入應用會創(chuàng)建新的Task棧。
4.Activity的affinity:
4.1.affinity是Activity內(nèi)的一個屬性(在AndroidManifest中對應屬性為taskAffinity)飞蚓。默認情況下滤港,擁有相同affinity的Activity屬于同一個Task中。
4.2.Task也有affinity屬性趴拧,它的affinity屬性由根Activity(創(chuàng)建Task時第一個被壓入棧的Activity)決定溅漾。
4.3.在默認情況下(我們什么都不設置),所有的Activity的affinity都從Application繼承著榴。也就是說Application同樣有taskAffinity屬性添履。
<application
? ? ? ? android:taskAffinity="gf.zy"
4.4.Application默認的affinity屬性為AndroidManifest的包名。
暫時就是這么多了脑又,如果還有不妥的地方我會補充的暮胧。接下來我們來正式看Activity的啟動模式:
二、Activity啟動模式:
1.默認啟動模式standard:
? ? 該模式可以被設定问麸,不在AndroidManifest設定時候叔壤,Activity的默認模式就是standard。在該模式下口叙,啟動的Activity會依照啟動順序被依次壓入Task中:
2.棧頂復用模式singleTop:
? ? 在該模式下,如果棧頂Activity為我們要新建的Activity(目標Activity)嗅战,那么就不會重復創(chuàng)建新的Activity妄田。
應用場景:
開啟渠道多,適合多應用開啟調(diào)用的Activity:通過這種設置可以避免已經(jīng)創(chuàng)建過的Activity被重復創(chuàng)建(多數(shù)通過動態(tài)設置使用驮捍,關于動態(tài)設置下面會詳細介紹)
3.棧內(nèi)復用模式singleTask:
? ? 與singleTop模式相似疟呐,只不過singleTop模式是只是針對棧頂?shù)脑兀鴖ingleTask模式下东且,如果task棧內(nèi)存在目標Activity實例启具,則:
將task內(nèi)的對應Activity實例之上的所有Activity彈出棧。
將對應Activity置于棧頂珊泳,獲得焦點鲁冯。
應用場景:
程序主界面,我們肯定不希望主界面被多創(chuàng)建色查,而且在主界面退出的時候退出整個App是最好的設想薯演。
耗費系統(tǒng)資源的Activity:對于那些及其耗費系統(tǒng)資源的Activity,我們可以考慮將其設為singleTask模式秧了,減少資源耗費(在創(chuàng)建階段耗費資源的情況跨扮,個人理解-。+)。
4.全局唯一模式singleInstance:
? ? 這是我們最后的一種啟動模式衡创,也是我們最惡心的一種模式:在該模式下帝嗡,我們會為目標Activity分配一個新的affinity,并創(chuàng)建一個新的Task棧璃氢,將目標Activity放入新的Task哟玷,并讓目標Activity獲得焦點。新的Task有且只有這一個Activity實例拔莱。? ? ? 如果已經(jīng)創(chuàng)建過目標Activity實例碗降,則不會創(chuàng)建新的Task,而是將以前創(chuàng)建過的Activity喚醒(對應Task設為Foreground(前臺)狀態(tài))
三塘秦、動態(tài)設置啟動模式
? ? 在上述所有情況讼渊,都是我們在AndroidManifest中設置的(通過launchMode屬性設置),這個被稱為靜態(tài)設置(我們寫程序?qū)懚嗔藭l(fā)現(xiàn)有靜態(tài)就有動態(tài)尊剔,而且靜態(tài)多數(shù)在xml設置爪幻,動態(tài)在java代碼設置-。)须误,接下來我們來看一下如何動態(tài)的設置Activity啟動方式挨稿。
注):如果同時有動態(tài)和靜態(tài)設置,那么動態(tài)的優(yōu)先級更高京痢。
1.關于動態(tài)設置與靜態(tài)設置的理解:
? ? 關于這個理解我是看過一篇文章奶甘,比較認同里面的思想,所以在這里也總結一下:
? ? 靜態(tài)設置祭椰,可以理解為通知別人:就是當我被創(chuàng)建的時候臭家,我告訴你我是通過這種模式啟動的。
? ? 動態(tài)設置方淤,可以理解為別人的要求:別人給我設一個Flag钉赁,我就以這種Flag的方式啟動。
? ? 可能這個沒什么用哈携茂,但是仔細想一下這種對程序的思想理解應該是正確的你踩。
標記位屬性
標記位屬性含義
FLAG_ACTIVITY_SINGLE_TOP????????指定啟動模式為棧頂復用模式(SingleTop)
FLAG_ACTIVITY_NEW_TASK????????指定啟動模式為棧內(nèi)復用模式
FLAG_ACTIVITY_CLEAR_TOP????????所有位于其上層的Activity都要移除,SingleTask模式默認具有此標記效果
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS????????具有該標記的Activity不會出現(xiàn)在歷史Activity的列表中讳苦,即無法通過歷史列表回到該Activity上
Intent.FLAG_ACTIVITY_NEW_TASK?
它會重新創(chuàng)建一個新的Activity带膜,不過與這種情況,比如說Task1中有A,B,C三個Activity,此時在C中啟動D的話鸳谜,如果在AndroidManifest.xml文件中給D添加了Affinity的值和Task中的不一樣的話钱慢,則會在新標記的Affinity所存在的Task中壓入這個Activity。如果是默認的或者指定的Affinity和Task一樣的話卿堂,就和標準模式一樣了啟動一個新的Activity.
FLAG_ACTIVITY_SINGLE_TOP
這個FLAG就相當于啟動模式中的singletop束莫,例如:原來棧中結構是A B C D懒棉,在D中啟動D,棧中的情況還是A,B,C,D览绿。
FLAG_ACTIVITY_CLEAR_TOP
這個FLAG就相當于啟動模式中的SingleTask策严,這種FLAG啟動的Activity會把要啟動的Activity之上的Activity全部彈出棧空間饿敲。例如:原來棧中的結構是A B C D 妻导,從D中跳轉(zhuǎn)到B,棧中的結構就變?yōu)榱薃 B了怀各。
FLAG_ACTIVITY_BROUGHT_TO_FRONT
這個網(wǎng)上很多人是這樣寫的倔韭。如果activity在task存在,拿到最頂端,不會啟動新的Activity瓢对。這個有可能會誤導大家寿酌! 他這個FLAG其實是這個意思!比如說我現(xiàn)在有A硕蛹,在A中啟動B醇疼,此時在A中Intent中加上這個標記。此時B就是以FLAG_ACTIVITY_BROUGHT_TO_FRONT方式啟動法焰,此時在B中再啟動C秧荆,D(正常啟動C,D),如果這個時候在D中再啟動B埃仪,這個時候最后的棧的情況是 A,C,D,B乙濒。如果在A,B,C,D正常啟動的話,不管B有沒有用FLAG_ACTIVITY_BROUGHT_TO_FRONT啟動卵蛉,此時在D中啟動B的話琉兜,還是會變成A,C,D,B的。
FLAG_ACTIVITY_NO_USER_ACTION
onUserLeaveHint()作為activity周期的一部分毙玻,它在activity因為用戶要跳轉(zhuǎn)到別的activity而要退到background時使用。比如,在用戶按下Home鍵廊散,它將被調(diào)用桑滩。比如有電話進來(不屬于用戶的選擇),它就不會被調(diào)用允睹。
那么系統(tǒng)如何區(qū)分讓當前activity退到background時使用是用戶的選擇运准?
它是根據(jù)促使當前activity退到background的那個新啟動的Activity的Intent里是否有FLAG_ACTIVITY_NO_USER_ACTION來確定的。
注意:調(diào)用finish()使該activity銷毀時不會調(diào)用該函數(shù)
FLAG_ACTIVITY_NO_HISTORY
意思就是說用這個FLAG啟動的Activity缭受,一旦退出胁澳,它不會存在于棧中,比如原來是A,B,C這個時候再C中以這個FLAG啟動D的米者,D再啟動E韭畸,這個時候棧中情況為A,B,C,E宇智。
參考文獻:
Android Activity的生命周期和啟動模式詳解
https://www.ktanx.com/blog/p/4665
細談Activity四種啟動模式
https://blog.csdn.net/zy_jibai/article/details/80587083
Android 面試之必問Android基礎
https://juejin.cn/post/6959472535108861959?from=main_page