Android中Activity生命周期和啟動(dòng)模式詳解
Activity生命周期經(jīng)典圖解:
按鍵對(duì)生命周期的影響:
BACK鍵:
當(dāng)我們按BACK鍵時(shí),我們這個(gè)應(yīng)用程序?qū)⒔Y(jié)束,這時(shí)候我們將先后調(diào)用onPause()->onStop()->onDestory()三個(gè)方法。
再次啟動(dòng)App時(shí),會(huì)執(zhí)行onCreate()->onStart()->onResume()
HOME鍵:
當(dāng)我們打開(kāi)應(yīng)用程序時(shí),比如瀏覽器,我正在瀏覽NBA新聞,看到一半時(shí),我突然想聽(tīng)歌,這時(shí)候我們會(huì)選擇按HOME鍵,然后去打開(kāi)音樂(lè)應(yīng)用程序,而當(dāng)我們按HOME的時(shí)候,Activity先后執(zhí)行了onPause()->onStop()這兩個(gè)方法,這時(shí)候應(yīng)用程序并沒(méi)有銷(xiāo)毀。
而當(dāng)我們從桌面再次啟動(dòng)應(yīng)用程序時(shí),則先后分別執(zhí)行了onRestart()->onStart()->onResume()三個(gè)方法。
一般Activity切換正常生命周期(這里的一般是指啟動(dòng)模式為standard,切換activity時(shí)沒(méi)有加flag標(biāo)志):
ActivityA啟動(dòng)ActivityB:
ActivityA 的生命周期onPause()->onStop(),
ActivityB的生命周期onCreate()->onStart()->onResume()。
ActivityB執(zhí)行finish返回ActivityA:
ActivityB的生命周期onPause()->onStop()->onDestory()
ActivityA的生命周期了onRestart()->onStart()->onResume()
注意:當(dāng)ActivityB定義為Dialog樣式時(shí),ActivityA的生命周期是不一樣的,
我們給ActivityB加上theme
<style name="MyDialogStyle"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowFrame">@null</item> <item name="android:windowNoTitle">true</item> <item name="android:windowIsFloating">true</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item> <item name="android:backgroundDimEnabled">true</item> </style>
這個(gè)時(shí)候,ActivityA啟動(dòng)ActivityB,B沒(méi)有完全遮擋A,ActivityB的生命周期跟剛才一樣,但是ActivityA并沒(méi)有執(zhí)行onStop()
還有一點(diǎn)需要特別注意,Activity中直接彈dialog,Acitivity的生命周期是不會(huì)變化的。網(wǎng)上有些說(shuō)法是會(huì)執(zhí)行onPause(),其實(shí)并沒(méi)有執(zhí)行!
另外還有幾個(gè)跟生命周期相關(guān)的方法
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); }
當(dāng)應(yīng)用運(yùn)行起來(lái)后就會(huì)開(kāi)啟一條線程,線程中會(huì)運(yùn)行一個(gè)任務(wù)棧,當(dāng)Activity實(shí)例創(chuàng)建后就會(huì)放入任務(wù)棧中。Activity啟動(dòng)模式的設(shè)置在AndroidManifest.xml文件中,通過(guò)配置Activity的屬性android:launchMode=""設(shè)置。
1. Standard模式(默認(rèn))
我們平時(shí)直接創(chuàng)建的Activity都是這種模式的Activity,這種模式的Activity的特點(diǎn)是:只要你創(chuàng)建了Activity實(shí)例,一旦激活該Activity,則會(huì)向任務(wù)棧中加入新創(chuàng)建的實(shí)例,退出Activity則會(huì)在任務(wù)棧中銷(xiāo)毀該實(shí)例。
standard模式是所啟動(dòng)的Activity都是在同一個(gè)task容器棧下,不會(huì)重新創(chuàng)建新的task容器棧。先壓入棧的Activity實(shí)例按順序入棧底,后入棧在棧頂,處于棧的頂部Activity實(shí)例處于活動(dòng)狀態(tài),其他處于非活動(dòng)狀態(tài)。按物理返回鍵,退出當(dāng)前所處活動(dòng)狀態(tài)Activity窗口,這樣就會(huì)從task容器棧中彈出,顯示在手機(jī)主屏幕上,從而,有非活動(dòng)狀態(tài)轉(zhuǎn)換成活動(dòng)的狀態(tài)。其次,standard容器??赡軙?huì)存在著相同的Activity實(shí)例,只有沒(méi)調(diào)用一次startActivity方法,就會(huì)創(chuàng)建目標(biāo)Activity實(shí)例對(duì)象壓入task容器棧。
如果Activity啟動(dòng)順序?yàn)锳->B->B->A->D,棧中的Acitivy為ABBAD(最先創(chuàng)建的A位于棧底,最后創(chuàng)建的D位于棧頂)
2. SingleTop模式
這種模式會(huì)考慮當(dāng)前要激活的Activity實(shí)例在任務(wù)棧中是否正處于棧頂,如果處于棧頂則無(wú)需重新創(chuàng)建新的實(shí)例,會(huì)重用已存在的實(shí)例,否則會(huì)在任務(wù)棧中創(chuàng)建新的實(shí)例。
SingleTop有個(gè)不錯(cuò)的用法是防止多次點(diǎn)擊創(chuàng)建多個(gè)Activity,無(wú)論start幾次,SingleTop模式能保證棧頂只有一個(gè)實(shí)例。 如果Activity啟動(dòng)順序?yàn)锳->B->B->A->D,棧中的Acitivy為ABAD(當(dāng)B位于棧頂時(shí),再次啟動(dòng)B的時(shí)候,B不會(huì)重新創(chuàng)建)
3. SingleTask模式
如果任務(wù)棧中存在該模式的Activity實(shí)例,則把棧中該實(shí)例以上的Activity實(shí)例全部移除,調(diào)用該實(shí)例的newInstance()方法重用該Activity,使該實(shí)例處?kù)稐m斘恢茫駝t就重新創(chuàng)建一個(gè)新的Activity實(shí)例。
singletask模式,特別需要注意了。啟動(dòng)的目標(biāo)Activity實(shí)例如果已經(jīng)存在task容器棧中,不管當(dāng)前實(shí)例處于棧的任何位置,是棧頂也好,棧底也好,還是處于棧中間,只要目標(biāo)Activity實(shí)例處于task容器棧中,都可以重用該Activity實(shí)例對(duì)象,然后,把處于該Activity實(shí)例對(duì)象上面全部Activity實(shí)例清除掉,并且,task容器棧中永遠(yuǎn)只有唯一實(shí)例對(duì)象,不會(huì)存在兩個(gè)相同的實(shí)例對(duì)象。所以,如果你想你的應(yīng)用不管怎么啟動(dòng)目標(biāo)Activity,都只有唯一一個(gè)實(shí)例對(duì)象,就使用這種啟動(dòng)模式。 如果Activity啟動(dòng)順序?yàn)锳->B->B->A->D,棧中的Acitivy為AD(當(dāng)A再次被啟動(dòng)時(shí),A會(huì)被移到棧頂,位于A上面的Acitivity全部會(huì)出棧)
4. SingleInstance模式
當(dāng)該模式Activity實(shí)例在任務(wù)棧中創(chuàng)建后,只要該實(shí)例還在任務(wù)棧中,即只要激活的是該類(lèi)型的Activity,都會(huì)通過(guò)調(diào)用實(shí)例的newInstance()方法重用該Activity,此時(shí)使用的都是同一個(gè)Activity實(shí)例,它都會(huì)處于任務(wù)棧的棧頂。此模式一般用于加載較慢的,比較耗性能且不需要每次都重新創(chuàng)建的Activity。
singleInstance啟動(dòng)模式,簡(jiǎn)單說(shuō)就是可以共享某個(gè)Activity。比如,應(yīng)用1的任務(wù)容器棧中創(chuàng)建了MainActivity實(shí)例,應(yīng)用2也要激活MainActivity,則不需要?jiǎng)?chuàng)建MainActivity實(shí)例,直接可以公用MainActivity實(shí)例。 尤其值得注意:應(yīng)用1啟動(dòng)MainActivity,按home鍵;打開(kāi)應(yīng)用2啟動(dòng)應(yīng)用1的MainActivity實(shí)例。在按home鍵,打開(kāi)應(yīng)用1,這時(shí)候應(yīng)用1的界面是應(yīng)該是處于MainActivity界面實(shí)例。 SingleInstance的一個(gè)任務(wù)棧中只有一個(gè)Activity,并保證不再有其他Activity實(shí)例進(jìn)入。
特別需要注意的生命周期onNewIntent
當(dāng)一個(gè)Activity被start,而不需要重新創(chuàng)建時(shí),就會(huì)執(zhí)行onNewIntent生命周期。如果一個(gè)Activity的啟動(dòng)模式是SingleTask,我們可以在onNewIntent中執(zhí)行一些刷新操作等。
我們一般會(huì)把MainAcitivy設(shè)置為SingleTask,除了保證MainActivity的唯一,還可以利用singleTask的特性做一些清理工作。自動(dòng)管理?xiàng)#N(xiāo)毀無(wú)用的Acitivity.
Intent Flags
Flags: 表示Intent的標(biāo)志位,常用于Activity的場(chǎng)景中,它和Activity的啟動(dòng)模式有著密切的聯(lián)系。
下面列舉的是和本文主題相關(guān)的Flags屬性:
Intent.FLAG_ACTIVITY_NEW_TASK (默認(rèn))
默認(rèn)的跳轉(zhuǎn)類(lèi)型,它會(huì)重新創(chuàng)建一個(gè)新的Activity,不過(guò)與這種情況,比如說(shuō)Task1中有A,B,C三個(gè)Activity,此時(shí)在C中啟動(dòng)D的話(huà),如果在AndroidManifest.xml文件中給D添加了Affinity的值和Task中的不一樣的話(huà),則會(huì)在新標(biāo)記的Affinity所存在的Task中壓入這個(gè)Activity。如果是默認(rèn)的或者指定的Affinity和Task一樣的話(huà),就和標(biāo)準(zhǔn)模式一樣了啟動(dòng)一個(gè)新的Activity.
FLAG_ACTIVITY_SINGLE_TOP這個(gè)FLAG就相當(dāng)于啟動(dòng)模式中的singletop,例如:原來(lái)?xiàng)V薪Y(jié)構(gòu)是A B C D,在D中啟動(dòng)D,棧中的情況還是A,B,C,D。
FLAG_ACTIVITY_CLEAR_TOP這個(gè)FLAG就相當(dāng)于啟動(dòng)模式中的SingleTask,這種FLAG啟動(dòng)的Activity會(huì)把要啟動(dòng)的Activity之上的Activity全部彈出??臻g。例如:原來(lái)?xiàng)V械慕Y(jié)構(gòu)是A B C D ,從D中跳轉(zhuǎn)到B,棧中的結(jié)構(gòu)就變?yōu)榱薃 B了。
FLAG_ACTIVITY_BROUGHT_TO_FRONT
這個(gè)網(wǎng)上很多人是這樣寫(xiě)的。如果activity在task存在,拿到最頂端,不會(huì)啟動(dòng)新的Activity。這個(gè)有可能會(huì)誤導(dǎo)大家! 他這個(gè)FLAG其實(shí)是這個(gè)意思!比如說(shuō)我現(xiàn)在有A,在A中啟動(dòng)B,此時(shí)在A中Intent中加上這個(gè)標(biāo)記。此時(shí)B就是以FLAG_ACTIVITY_BROUGHT_TO_FRONT方式啟動(dòng),此時(shí)在B中再啟動(dòng)C,D(正常啟動(dòng)C,D),如果這個(gè)時(shí)候在D中再啟動(dòng)B,這個(gè)時(shí)候最后的棧的情況是 A,C,D,B。如果在A,B,C,D正常啟動(dòng)的話(huà),不管B有沒(méi)有用FLAG_ACTIVITY_BROUGHT_TO_FRONT啟動(dòng),此時(shí)在D中啟動(dòng)B的話(huà),還是會(huì)變成A,C,D,B的。
FLAG_ACTIVITY_NO_USER_ACTION
onUserLeaveHint()作為activity周期的一部分,它在activity因?yàn)橛脩?hù)要跳轉(zhuǎn)到別的activity而要退到background時(shí)使用。比如,在用戶(hù)按下Home鍵,它將被調(diào)用。比如有電話(huà)進(jìn)來(lái)(不屬于用戶(hù)的選擇),它就不會(huì)被調(diào)用。
那么系統(tǒng)如何區(qū)分讓當(dāng)前activity退到background時(shí)使用是用戶(hù)的選擇?
它是根據(jù)促使當(dāng)前activity退到background的那個(gè)新啟動(dòng)的Activity的Intent里是否有FLAG_ACTIVITY_NO_USER_ACTION來(lái)確定的。
注意:調(diào)用finish()使該activity銷(xiāo)毀時(shí)不會(huì)調(diào)用該函數(shù)
FLAG_ACTIVITY_NO_HISTORY
意思就是說(shuō)用這個(gè)FLAG啟動(dòng)的Activity,一旦退出,它不會(huì)存在于棧中,比如原來(lái)是A,B,C這個(gè)時(shí)候再C中以這個(gè)FLAG啟動(dòng)D的,D再啟動(dòng)E,這個(gè)時(shí)候棧中情況為A,B,C,E。
Activity相關(guān)屬性taskAffinity
Activity 中的 android:taskAffinity 這個(gè)屬性介紹:
Activity為T(mén)ask擁有的一個(gè)affinity。擁有相同的affinity的Activity理論上屬于相同的Task(在用戶(hù)的角度是相同的“應(yīng)用程序”)。Task的affinity是由它的根Activity決定的。
affinity決定兩件事情——Activity重新宿主的Task(參考allowTaskReparenting特性)和使用FLAG_ACTIVITY_NEW_TASK標(biāo)志啟動(dòng)的Activity宿主的Task。
默認(rèn)情況,一個(gè)應(yīng)用程序中的所有Activity都擁有相同的affinity。捏可以設(shè)定這個(gè)特性來(lái)重組它們,甚至可以把不同應(yīng)用程序中定義的Activity放置到相同的Task中。為了明確Activity不宿主特定的Task,設(shè)定該特性為空的字符串。
如果這個(gè)特性沒(méi)有設(shè)置,Activity將從應(yīng)用程序的設(shè)定那里繼承下來(lái)(參考<application>元素的taskAffinity特性)。應(yīng)用程序默認(rèn)的affinity的名字是<manifest>元素中設(shè)定的package名。
- Android Activity生命周期和堆棧管理的詳解
- Android Activity的生命周期詳細(xì)介紹
- android中Activity詳解(生命周期、以各種方式啟動(dòng)Activity、狀態(tài)保存,完全退出等)
- android基礎(chǔ)總結(jié)篇之一:Activity生命周期
- Android Activity生命周期詳解
- Android開(kāi)發(fā)之a(chǎn)ctivity的生命周期詳解
- Android開(kāi)發(fā)中Activity的生命周期及加載模式詳解
- Android開(kāi)發(fā)系列二之窗口Activity的生命周期
- Android Activity 橫豎屏切換的生命周期
- Android中Fragment與Activity的生命周期對(duì)比
- Android非異常情況下的Activity生命周期分析
相關(guān)文章
Android編程調(diào)用Camera和相冊(cè)功能詳解
這篇文章主要介紹了Android編程調(diào)用Camera和相冊(cè)功能,結(jié)合實(shí)例形式分析了Android的拍照及相冊(cè)調(diào)用功能相關(guān)實(shí)現(xiàn)技巧與操作注意事項(xiàng),需要的朋友可以參考下2017-02-02Android應(yīng)用中使用及實(shí)現(xiàn)系統(tǒng)“分享”接口實(shí)例
為了應(yīng)用的推廣、傳播,很多的應(yīng)用中都有“分享”功能,這篇文章主要介紹了Android應(yīng)用中使用及實(shí)現(xiàn)系統(tǒng)“分享”接口實(shí)例,有興趣的可以了解一下。2016-12-12Android利用貝塞爾曲線繪制動(dòng)畫(huà)的示例代碼
本篇就借由動(dòng)畫(huà)驅(qū)動(dòng)貝塞爾曲線繪制看看動(dòng)起來(lái)的貝塞爾曲線什么效果。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-05-05Android中src和background的區(qū)別詳解
這篇文章主要介紹了Android中src和background的區(qū)別詳解的相關(guān)資料,需要的朋友可以參考下2016-09-09Android 調(diào)用系統(tǒng)照相機(jī)拍照和錄像
本文主要介紹Android 調(diào)用系統(tǒng)照相機(jī)拍照和錄像的資料,這里整理了詳細(xì)的代碼,有需要的小伙伴可以參考下2016-09-09Android clipChildren屬性實(shí)例詳解
本文主要介紹Android clipChildren的屬性,這里對(duì)clipChildren屬性做了一個(gè)小例子,展示了效果圖和實(shí)例代碼,方便大家觀看理解2016-07-07談?wù)凙ndroid里的Context的使用實(shí)例
這篇文章主要介紹了談?wù)凙ndroid里的Context的使用實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2016-11-11