Activity的生命週期和啟動模式詳解
Activity生命週期經典圖解:
按鍵對生命週期的影響:
BACK鍵:
當我們按BACK鍵時,我們這個應用程式將結束,這時候我們將先後呼叫onPause()->onStop()->onDestory()三個方法。
再次啟動App時,會執行onCreate()->onStart()->onResume()
HOME鍵:
當我們開啟應用程式時,比如瀏覽器,我正在瀏覽NBA新聞,看到一半時,我突然想聽歌,這時候我們會選擇按HOME鍵,然後去開啟音樂應用程式,而當我們按HOME的時候,Activity先後執行了onPause()->onStop()這兩個方法,這時候應用程式並沒有銷燬。
而當我們從桌面再次啟動應用程式時,則先後分別執行了onRestart()->onStart()->onResume()三個方法。一般Activity切換正常生命週期(這裡的一般是指啟動模式為standard,切換activity時沒有加flag標誌):
ActivityA啟動ActivityB:
ActivityA 的生命週期onPause()->onStop(),
ActivityB的生命週期onCreate()->onStart()->onResume()。
ActivityB執行finish返回ActivityA:ActivityB的生命週期onPause()->onStop()->onDestory()
ActivityA的生命週期了onRestart()->onStart()->onResume()
注意:當ActivityB定義為Dialog樣式時,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>
這個時候,ActivityA啟動ActivityB,B沒有完全遮擋A,ActivityB的生命週期跟剛才一樣,但是ActivityA並沒有執行onStop()
還有一點需要特別注意,Activity中直接彈dialog,Acitivity的生命週期是不會變化的。網上有些說法是會執行onPause(),其實並沒有執行!
另外還有幾個跟生命週期相關的方法
@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);
}
當應用執行起來後就會開啟一條執行緒,執行緒中會執行一個任務棧,當Activity例項建立後就會放入任務棧中。Activity啟動模式的設定在AndroidManifest.xml檔案中,通過配置Activity的屬性android:launchMode=""設定。
1. Standard模式(預設)
我們平時直接建立的Activity都是這種模式的Activity,這種模式的Activity的特點是:只要你建立了Activity例項,一旦啟用該Activity,則會向任務棧中加入新建立的例項,退出Activity則會在任務棧中銷燬該例項。
standard模式是所啟動的Activity都是在同一個task容器棧下,不會重新建立新的task容器棧。先壓入棧的Activity例項按順序入棧底,後入棧在棧頂,處於棧的頂部Activity例項處於活動狀態,其他處於非活動狀態。按物理返回鍵,退出當前所處活動狀態Activity視窗,這樣就會從task容器棧中彈出,顯示在手機主螢幕上,從而,有非活動狀態轉換成活動的狀態。其次,standard容器棧可能會存在著相同的Activity例項,只有沒呼叫一次startActivity方法,就會建立目標Activity例項物件壓入task容器棧。
如果Activity啟動順序為A->B->B->A->D,棧中的Acitivy為ABBAD(最先建立的A位於棧底,最後建立的D位於棧頂)
2. SingleTop模式
這種模式會考慮當前要啟用的Activity例項在任務棧中是否正處於棧頂,如果處於棧頂則無需重新建立新的例項,會重用已存在的例項,否則會在任務棧中建立新的例項。
SingleTop有個不錯的用法是防止多次點選建立多個Activity,無論start幾次,SingleTop模式能保證棧頂只有一個例項。 如果Activity啟動順序為A->B->B->A->D,棧中的Acitivy為ABAD(當B位於棧頂時,再次啟動B的時候,B不會重新建立)
3. SingleTask模式
如果任務棧中存在該模式的Activity例項,則把棧中該例項以上的Activity例項全部移除,呼叫該例項的newInstance()方法重用該Activity,使該例項處於棧頂位置,否則就重新建立一個新的Activity例項。
singletask模式,特別需要注意了。啟動的目標Activity例項如果已經存在task容器棧中,不管當前例項處於棧的任何位置,是棧頂也好,棧底也好,還是處於棧中間,只要目標Activity例項處於task容器棧中,都可以重用該Activity例項物件,然後,把處於該Activity例項物件上面全部Activity例項清除掉,並且,task容器棧中永遠只有唯一例項物件,不會存在兩個相同的例項物件。所以,如果你想你的應用不管怎麼啟動目標Activity,都只有唯一一個例項物件,就使用這種啟動模式。 如果Activity啟動順序為A->B->B->A->D,棧中的Acitivy為AD(當A再次被啟動時,A會被移到棧頂,位於A上面的Acitivity全部會出棧)
4. SingleInstance模式
當該模式Activity例項在任務棧中建立後,只要該例項還在任務棧中,即只要啟用的是該型別的Activity,都會通過呼叫例項的newInstance()方法重用該Activity,此時使用的都是同一個Activity例項,它都會處於任務棧的棧頂。此模式一般用於載入較慢的,比較耗效能且不需要每次都重新建立的Activity。
singleInstance啟動模式,簡單說就是可以共享某個Activity。比如,應用1的任務容器棧中建立了MainActivity例項,應用2也要啟用MainActivity,則不需要建立MainActivity例項,直接可以公用MainActivity例項。 尤其值得注意:應用1啟動MainActivity,按home鍵;開啟應用2啟動應用1的MainActivity例項。在按home鍵,開啟應用1,這時候應用1的介面是應該是處於MainActivity介面例項。 SingleInstance的一個任務棧中只有一個Activity,並保證不再有其他Activity例項進入。
特別需要注意的生命週期onNewIntent
當一個Activity被start,而不需要重新建立時,就會執行onNewIntent生命週期。如果一個Activity的啟動模式是SingleTask,我們可以在onNewIntent中執行一些重新整理操作等。
我們一般會把MainAcitivy設定為SingleTask,除了保證MainActivity的唯一,還可以利用singleTask的特性做一些清理工作。自動管理棧,銷燬無用的Acitivity.
Intent Flags
Flags: 表示Intent的標誌位,常用於Activity的場景中,它和Activity的啟動模式有著密切的聯絡。下面列舉的是和本文主題相關的Flags屬性:
Intent.FLAG_ACTIVITY_NEW_TASK (預設)
預設的跳轉型別,它會重新建立一個新的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中跳轉到B,棧中的結構就變為了A B了。FLAG_ACTIVITY_BROUGHT_TO_FRONT
這個網上很多人是這樣寫的。如果activity在task存在,拿到最頂端,不會啟動新的Activity。這個有可能會誤導大家! 他這個FLAG其實是這個意思!比如說我現在有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因為使用者要跳轉到別的activity而要退到background時使用。比如,在使用者按下Home鍵,它將被呼叫。比如有電話進來(不屬於使用者的選擇),它就不會被呼叫。那麼系統如何區分讓當前activity退到background時使用是使用者的選擇?
它是根據促使當前activity退到background的那個新啟動的Activity的Intent裡是否有FLAG_ACTIVITY_NO_USER_ACTION來確定的。
注意:呼叫finish()使該activity銷燬時不會呼叫該函式
FLAG_ACTIVITY_NO_HISTORY
意思就是說用這個FLAG啟動的Activity,一旦退出,它不會存在於棧中,比如原來是A,B,C這個時候再C中以這個FLAG啟動D的,D再啟動E,這個時候棧中情況為A,B,C,E。Activity相關屬性taskAffinity
Activity 中的 android:taskAffinity 這個屬性介紹:Activity為Task擁有的一個affinity。擁有相同的affinity的Activity理論上屬於相同的Task(在使用者的角度是相同的“應用程式”)。Task的affinity是由它的根Activity決定的。
affinity決定兩件事情——Activity重新宿主的Task(參考allowTaskReparenting特性)和使用FLAG_ACTIVITY_NEW_TASK標誌啟動的Activity宿主的Task。
預設情況,一個應用程式中的所有Activity都擁有相同的affinity。捏可以設定這個特性來重組它們,甚至可以把不同應用程式中定義的Activity放置到相同的Task中。為了明確Activity不宿主特定的Task,設定該特性為空的字串。
如果這個特性沒有設定,Activity將從應用程式的設定那裡繼承下來(參考<application>元素的taskAffinity特性)。應用程式預設的affinity的名字是<manifest>元素中設定的package名。
歡迎掃描二維碼,關注公眾號
相關文章
- Android Activity的生命週期和啟動模式詳解Android模式
- Activity的生命週期和啟動模式模式
- Activity生命週期與啟動模式模式
- Activity生命週期與啟動模式筆記模式筆記
- Android Activity生命週期詳解Android
- Android開發藝術(1)——Activity的生命週期和啟動模式Android模式
- View和Activity的生命週期View
- Activity生命週期
- activity生命週期的onPause和onStop
- Activity的啟動模式詳解模式
- View生命週期與Activity生命週期的關係View
- Android Activity是如何啟動的?Activity的生命週期是如何呼叫的?Android
- Android入門教程之Activity(生命週期,啟動...)Android
- 框架層理解Activity生命週期(APP啟動過程)框架APP
- Activity生命週期onDestroy
- 為什麼 bindService 能和 Activity 的生命週期聯動?
- [Android]Activity的生命週期Android
- activity的生命週期(總結)
- Android Activity生命週期Android
- Activity生命週期總結
- vue生命週期詳解Vue
- React生命週期詳解React
- 詳解vue生命週期Vue
- Service生命週期詳解
- Activity 知識梳理(1) Activity生命週期
- 關於activity的生命週期1
- Vue的生命週期的詳解Vue
- iOS-APP的啟動流程和生命週期iOSAPP
- 深入學習Activity生命週期
- Activity簡介及生命週期
- Java類的生命週期詳解Java
- 詳解Vue生命週期【上】Vue
- React 元件生命週期詳解React元件
- React元件生命週期詳解React元件
- Android 元件系列-----Activity生命週期Android元件
- Activity生命週期深入理解2
- Android View的生命週期詳解AndroidView
- android解鎖屏時Activity生命週期的變化Android