Activity生命周期
典型生命周期
指在有用戶參與的情況下,Activity經歷的生命周期的改變。
正常情況下,Activity會經歷如下的生命周期:
- onCreate,表示Activity正在被創建,可以做一些初始化的工作,比如SetContentView,初始化所需要的數據。
- onRestart,表示Activity正在被重啟,一般情況下,當當前Activity從不可見重新變為可見,onRestart被調用。這種情況一般是用戶的行為導致的,比如用戶按Home鍵切換到桌面,或者用戶打開了一個新的Activity,當前的Activity就會暫停,接著用戶又回到了這個Activity,就會出現這種情況。
- onStart,表示Activity正在被啟動,即將開始,這是Activity已經可見了,但是還沒有出現在前臺,還無法和用戶交互。
- onResume,Activity已經可見了,并且出現在前臺并開始活動。
- onPause,Activity正在停止,緊接著onStop會被調用,可以做一些不耗時的操作。
- onStop,表示Activity即將停止。
- onDestory,Activity即將被銷毀,可以做一些回收工作和最終的資源釋放。
整個生命周期如下圖所示:
生命周期
注意事項
- 針對一個特定的Activity,第一次啟動,回調為onCreate->onStart->onResume
- 用戶打開新的Activity或切換到桌面,回調為onPause->onStop。如果Activity設置了透明主題,不會回調onStop。
- 用戶再次回到原Activity,回調為onRestart->onStart->onResume 。
- 用戶按back鍵回退時,回調為onPause->onStop->onDestory。
- 新Activity啟動之前棧頂得Activity需要先onPause,新的Activity才啟動。
- onStart和onStop是否可見,onResume,onPause針對是否位于前臺。
異常生命周期
Activity被系統收回或者由于當前設備的Configuration發生變化從而導致Activity被銷毀重建。
資源相關的系統配置發生改變導致Activity被殺死并重新創建
當系統配置發生改變后,Activity被銷毀,其onPause,onStop,onDestory均會被調用,同時由于Activity是在異常情況下終止的,系統會調用onSaveInstanceState來保存當前Activity的狀態。這個方法的調用時機是在onStop之前,可能在onPause之前也可能在onPause之后。當Activity被重新創建后,系統會調用onRestoreInstanceState,并把Activity銷毀時onSaveInstanceState方法所保存的Bundle對象同時傳給onRestoreInstanceState和onCreate方法。
onRestoreInstanceState與onCreate的區別就是onRestoreInstanceState一旦被調用則參數肯定不是null。
資源內存不足導致低優先級的Activity被殺死
Activity的優先級分為:
- 前臺Activity,正在和用戶交互的Activity,優先級最高。
- 可見但非前臺Activity,比如Activity彈出了一個對話框,導致Activity可見,但是位于后臺無法和用戶直接交互。
- 后臺Activity,已經被暫停的Activity,比如執行了onStop,優先級最低。
系統配置發生變化,不重新創建的方法
設置Activity的configChanges屬性。常用的有local,orientation,keyboardHidden。
Activity啟動模式
任務棧是一個先進后出的棧結構。四種啟動模式:standard,singleTask,singleTop,singleIntance。
standard
系統默認模式,每次啟動一個Activity都會重新創建一個新的實例,不管這個Activity是否有實例是否存在。誰啟動了Activity則activiyt就運行在啟動他的那個activity所在的棧中。
如果是非Activity的Context啟動了Activity,則需要設置FLAG_ACTIVITY_NEW_TASK標記,這樣啟動的時候就會為它創建一個新的任務棧,這個時候待啟動的Activity實際上是以singletask模式啟動的。
singleTop
棧頂復用模式,只有在Activity在棧頂有實例,則復用,如果不在棧頂則新建實例。
singleTask
棧內復用,在同一個棧內只存在一個實例,如果已經在棧里則清除該實例頂的所有其他Activity對象,否則新建一個實例。具有清除棧頂操作。
singleInstance
單例模式,整個應用內只有一個實例。
任務棧
什么是Activity所需要的任務棧?從參數TaskAffinity說起,該單詞可翻譯為任務相關性,這個參數表示了一個Activity所需要的任務棧的名字,默認情況下,所有Activity所需的任務棧的名稱為應用的報名。TaskAffinity屬性主要和SingleTask啟動模式或者allowTaskReparenting屬性配對使用,其他情況下沒有意義。另外任務棧分為前臺任務棧和后臺任務棧,后臺任務棧中的Activity位于暫停狀態,用戶可以通過切換將后臺任務棧再次調到前臺。
當TaskAffinity和singleTask啟動模式配對使用的時候,它具有該模式的Activity的目前任務棧的名稱,待啟動的Activity會運行在名字和TaskAffinity相同的任務棧中。
啟動模式的指定
兩種方式,1.在AndroidMenifest文件中為Activity指定,設置android:launchMode屬性。2.在Intent中設置標記位,通過intent的addFlags方法來設置。
兩種方式區別,優先級第二種高,限定范圍不同,第一種無法直接為Activity設置FLAG_ACTIVITY_CLEAR_TOP,第二種無法為Activity指定singleInstance模式。
Activity的Flags
- FLAG_ACTIVITY_NEW_TASK 相當于為Activity指定了‘singleTask’啟動模式
- FLAG_ACTIVITY_SINGLE_TOP 相當于制定了‘singleTop’啟動模式
- FLAG_ACTIVITY_CLEAR_TOP 當啟動時,同一個任務棧中所有的位于它上面的Activity都要出棧。這個模式一般需要和FLAG_ACTIVITY_NEW_TASK配合使用,這種情況下,被啟動的Activity如果已經存在,那么系統就會調用它的onNewIntent。如果被啟動的Activity采用的時standard模式,則它連同它之上的Activity都要出棧,系統會創建新的Activity
- FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS Activity不會出現在歷史Activity列表中。等同于android:excludeFromRecents="true"。
IntentFilter匹配規則
Activity的啟動分為顯示和隱式調用。顯示調用需要明確地指定啟動對象的組件信息,包括包名和類名,而隱式調用則不需要明確指定組件信息,原則上一個Intent不應該既是顯示調用又是隱式調用,如果二者共存的話以顯示調用為主。
IntentFilter中的過濾信息有action,category,data。
action匹配規則
action是一個字符串,action的匹配規則是Intent中的action必須能夠和過濾規則中得action匹配,這里說的匹配指字符串完全一樣。一個過濾規則中可以有多個action那么只要Intent中的action能夠和過濾規則中得任何一個相同則匹配成功。
category匹配規則
如果Intent中又category,不管幾個category,對于每一個category,它必須是過濾規則中已經定義了的category。如果Intent中沒有category則仍然匹配成功。為了保證activity接收隱式調用,就必須在intent-filter中指定android.intent.catogroy.DEFAULT這個category。
data匹配規則
如果過濾規則中定義了data,那么Intent中必須也要定義可匹配的data。
data分為兩部分,mimeType和URI。mimeType指媒體類型,比如image/jpeg,audio/mpeg4-generic等可以表示圖片,文本,視頻等不同的媒體格式。而URI中包含的數據就比較多了。URI的結構為:
<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
Scheme,URI的模式比如http,file,content等。如果URI中沒有指定scheme,則整個URI的其他參數無效。
Host,URI的主機名,必須有Host。
Port,URI中得端口號。
Path,pathPattern,pathPrefix,三個參數表示路徑信息,其中path表示完整的路徑信息,pathPatter也表示完整的路徑信息,但是里面可以包含通配符。pathPrefix表示路徑的前綴。
Intent必須包含data數據,并且data數據能夠完全匹配過濾規則中的某一個data。
Fragment 生命周期
生命周期如下所示:
與activity生命周期對比:
生命周期分析
- 當一個fragment被創建的時候,它會經歷以下狀態.
- onAttach()
- onCreate()
- onCreateView()
- onActivityCreated()
- 當這個fragment對用戶可見的時候,它會經歷以下狀態。
- onStart()
- onResume()
- 當這個fragment進入“后臺模式”的時候,它會經歷以下狀態。
- onPause()
- onStop()
- 當這個fragment被銷毀了(或者持有它的activity被銷毀了),它會經歷以下狀態。
- onPause()
- onStop()
- onDestroyView()
- onDestroy() // 本來漏掉類這個回調,感謝xiangxue336提出。
- onDetach()
- 就像activitie一樣,在以下的狀態中,可以使用Bundle對象保存一個fragment的對象。
- onCreate()
- onCreateView()
- onActivityCreated()
- fragments的大部分狀態都和activitie很相似,但fragment有一些新的狀態。
- onAttached() —— 當fragment被加入到activity時調用(在這個方法中可以獲得所在的activity)。
- onCreateView() —— 當activity要得到fragment的layout時,調用此方法,fragment在其中創建自己的layout(界面)。
- onActivityCreated() —— 當activity的onCreated()方法返回后調用此方法
- onDestroyView() —— 當fragment中的視圖被移除的時候,調用這個方法。
- onDetach() —— 當fragment和activity分離的時候,調用這個方法。
一旦activity進入resumed狀態(也就是running狀態),你就可以自由地添加和刪除fragment了。因此,只有當activity在resumed狀態時,fragment的生命周期才能獨立的運轉,其它時候是依賴于activity的生命周期變化的。