Android進階(1)| 深入理解Activity

本節目錄
一.Activity的生命週期
1.典型情況下的生命週期分析
在正常情況下Activity從建立到到銷燬會經歷如下過程:
(1) onCreate():
- 呼叫前:Activit剛剛啟動
- 呼叫時:進行一些初始化的工作
- 呼叫後:準備呼叫onStart()
(2) onStart():
- 呼叫前:onCreate()方法剛結束
- 呼叫時:Activity正在被啟動
- 呼叫後:Activity已經顯示出來,但是無法進行互動。準備呼叫onResume()
(3)onResume():
- 呼叫前:onStart()剛結束
- 呼叫時:Activity由後臺開始轉移到前臺
- 呼叫後:Activity對於使用者來說完全可見並且可以進行互動。準備呼叫onPause()
(4)onPause():
- 呼叫前:onResume()剛結束
- 呼叫時:Activity正在停止
- 呼叫後:Activity已經不可見。準備呼叫onStop()
(5)onStop():
- 呼叫前:onPause()剛結束
- 呼叫時:Activity即將停止
- 呼叫後:Activity正在停止或即將被銷燬。準備呼叫onDestroy()
(6)onDestroy():
- 呼叫前:onStop()剛結束
- 呼叫時:Activity即將被銷燬
- 呼叫後:Activity被銷燬,調出任務棧
特殊:onRestart():
- 呼叫前:onStop()剛結束
- 呼叫時:Activity正在被重新啟動
- 呼叫後:Activity由不可見狀態再次變為可見狀態。準備呼叫onResume()
2.Activity生存期
(1)完整生存期
Activity在onCreate()和onDestroy()中所經歷的就是完整生存期。我們一般在onCreate()方法中完成一些初始化的操作,在onDestroy()方法中完成釋放記憶體的操作。
(2)可見生存期
Activity在onStart()和onStop()中所經歷的就是可見生存期。在這個階段其實Activity已經是顯示了出來,但我們使用者不一定看的見,也不一定能夠與Activity進行互動操作。
(3)前臺生存期
Activity在onResume()和onPause()中所經歷的就是前臺生存期。在這個階段中的Activity是可以與使用者被使用者所見並且進行互動的。
3.異常情況下的生命週期分析
(1)資源相關配置發生改變導致Activity被殺死和重新建立
當系統配置發生變化時,Activity會被銷燬,即開始呼叫onPause()、onStop()和onDestroy(),但是在呼叫onStop()之前系統會先呼叫onSaveInstanceState()方法來讓當前Activity中的部分資料儲存在Bundle中。在Activity銷燬之後系統會再次重新建立該Activity,並且在onResume()之前呼叫onRestoreInstanceState()方法,將Bundle中的資料恢復出來。
注意:系統只在Activity異常終止的時候才會呼叫onSaveInstanceState()和onRestoreInstanceState()方法,其他正常情況下是不會呼叫的。
(2)資源記憶體不足導致低優先順序的Activity被殺死和重新建立
優先順序:Activity按照優先順序從高到低分別是:前臺Activity、可見但非前臺Activity和後臺Activity。
當系統的記憶體不足時,Activity優先順序越低則越容易被系統殺死。當然此時Activity也是處於異常終止,因此生命週期是和第(1)種是一樣的,這裡就不多分析。
(3)通過修改配置使得Activity在異常情況下不被自動建立
在(1)和(2)中我們分析了Activity在異常情況下的生命週期,它們都是在出現異常時先銷燬然後重新建立。不過我們可以修改Activity中的的 android:configChanges
屬性來指定一些情況下Activity在被銷燬之後不被建立。

configChanges專案和含義
android:configChanges:orientation|keyboardHidden
表示當螢幕方向改變或者鍵盤的可用性發生了改變時Activity在被銷燬之後不會重新建立。
注意:當我們設定屬性之後Activity不會呼叫onSaveInstanceState()和onRestoreInstanceState()方法。但是它會呼叫onConfigChanged()方法。
二.Activity的啟動模式
1.深入理解四種LaunchMode
(1)standard
standard模式是Activity預設的啟動方式,它啟動Activity的具體方式是:每當啟動一個活動,就會建立一個該活動的例項,該例項就會在任務棧中入棧並且處於棧頂的位置。
注意:每個Activity例項可以進入不同的任務棧中。例如Activity A和Activity B分別位於棧-1和棧-2當中,當A啟動Activity C時,C的例項就會到棧-1的棧頂;當B啟動C時,C的另一個例項就會到棧-2的棧頂。
(2)singleTop
singleTop啟動的具體方式是:每當啟動一個活動時,系統會先檢視它所在的任務棧,如果任務棧的棧頂就是該活動,則不會再建立。否則就是和standard模式一樣。
(3)singleTask
singleTask的啟動方式是:當啟動一個活動是,系統會先遍歷它所在的任務棧,如果棧中存在該活動的例項,則該活動上方的所有活動都會出棧,也就是說該活動會被推到棧頂。否則還是會在棧頂重新建立一個該活動的例項。
舉例:
- 棧-1中從上到下為活動CBA,此時Activity D以SingleTask模式啟動,其所需要的任務棧為棧-2,則此時系統會建立一個棧-2並且將D入棧。
- 棧-1情況不變,此時D所需的任務棧為棧-1,則這次系統會將D放入棧-1的棧頂,此時棧-1的情況就是DCBA。
- 假設棧-1此時從上到下是CBDA,此時D啟動所需的任務棧是棧-1,則此時棧-1中C和B會出棧,而D不會再次建立例項。棧-1最後的情況就是DA。
(4)singleInstance
singleInstance的啟動方式是:活動啟動時系統會建立一個新棧,該活動就會單獨的在這個棧當中,後面如果再次啟動該活動也不會再次建立例項。
2.TaskAffnity屬性
TaskAffnity翻譯為任務相關性,該引數標識了一個Activity所需要的任務棧的名字。在預設情況下,所有Activity所需的任務棧的名字都是應用的包名,但是我們可以為Activity的TaskAffnity屬性單獨設定所需棧的名字。
注意:TaskAffnity屬性不能設定為包名,否則相當於無效設定;TaskAffnity只能和singleTask啟動模式搭配使用,在其他情況下屬於沒有意義。
3.設定Activity的啟動方式
(1)設定 android:launchMode
在AndroidMenifest中找到活動的 android:launchMode
屬性進行修改。
舉例:設定Activity為singleTop啟動模式 android:launchMode:singleTop
。
(2)設定標誌位
我們可以在Intent中使用addFlags()方法來設定啟動模式。
舉例:
Intent intent = new Intent(MainActivity.this,SecondActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//設定標識位 startActivity(intent);
4.Activity常用的的Flags
1.FLAG_ACTIVITY_NEW_TASK
為Activity指定為singleTask啟動模式。
2.FLAG_ACTIVITY_SINGLE_TOP
為Activity指定為singleTop啟動模式。
3.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有這個標記的Activity不會出現在歷史Activity的列表當中。
三.IntentFilter匹配規則
使用物件:啟動Activity的方法有兩種:顯示Intent和隱式Intent。而在隱式Intent我們就會用到IntentFilter匹配規則。
基本規則:(1)一個intent只有同時匹配某個Activity的intent-filter中的action、category、data中的過濾規則才算完全匹配,才能啟動該Activity。 (2)一個Activity可以有多個 intent-filter,一個 intent只要成功匹配任意一組 intent-filter,就可以啟動該Activity。
下面來具體介紹每種屬性的匹配規則。
1.action匹配規則
匹配規則:Intent中的action必須存在且必須和過濾規則中的任意一個action相同。
注意:在action匹配規則中是區分大小寫的,即如果字元相同,但是大小寫不同則無法進行匹配。
2.category匹配規則
匹配規則:如果Intent中出現了category,則必須和過濾規則當中的一個category相同;如果Intent中沒有出現category,則系統會給Activity預設加上了 < category android:name="android.intent.category.DEAFAULT" />
屬性值,此時category也能匹配成功。
3.data匹配規則
data的組成:data由兩部分組成:mimeType和URI。
匹配規則:如果intent-filter中有定義data,那麼Intent中也必須也要含有data資料,並且data資料能夠匹配過濾規則中的某一個data。如果沒有是定義data過濾規則,則在啟動Activity時不用考慮data部分。
注意:(1)data中的過濾規則我們可以分開定義,即我們可以定義 <data android:mimeType
和 <data android:scheme
。 (2)如果我們只在過濾規則中定義了mimeType,那麼URI部分會使用其預設值content或file。也就是說雖然沒有指定URI,但是Intent中的URI部分必須是content或file。 (3)在為Intent指定data時我們需要使用setDataAndType()方法。
4.匹配判斷的方法
(1)採用PackgeManager的resolveActivity方法,如果找不到匹配的Activity則會返回null。
(2)採用Intent的resolveActivity方法,如果找不到匹配的的Activity則會返回null。