Activity生命周期的分析
從兩種情況來分析
- 典型情況(用戶正常參與的情況)
- 異常情況(由于內(nèi)存不足谱煤,被系統(tǒng)殺掉晕换、Configuration改變等)
典型情況下的生命周期分析
-
onPause不能太耗時瘩缆,因為上一個Activity執(zhí)行完之后 下個Activity的onCreate/onStart/onResume/onResume才能執(zhí)行循帐,所以不要在onPause中執(zhí)行耗時才做筝家,使新的Activity盡快切到前臺
從Activity1到Activity2 09-06 20:56:55.190 com.xk.chapter1 D/Activity1: onCreate--> 09-06 20:56:55.210 com.xk.chapter1 D/Activity1: onStart--> 09-06 20:56:55.210 com.xk.chapter1 D/Activity1: onResume--> 09-06 20:56:59.500 com.xk.chapter1 D/Activity1: onPause耗時操作開始--> 09-06 20:57:01.510 com.xk.chapter1 D/Activity1: onPause耗時操作結(jié)束--> Activity2出現(xiàn) 09-06 20:57:01.520 com.xk.chapter1 D/Activity2: onCreate--> 09-06 20:57:01.520 com.xk.chapter1 D/Activity2: onStart--> 09-06 20:57:01.520 com.xk.chapter1 D/Activity2: onResume--> 09-06 20:57:01.990 com.xk.chapter1 D/Activity1: onStop--> 從Activity2返回Activity1 09-06 21:01:13.490 com.xk.chapter1 D/Activity2: onPause耗時操作開始--> 09-06 21:01:15.490 com.xk.chapter1 D/Activity2: onPause耗時操作結(jié)束--> Activity1 09-06 21:01:15.490 com.xk.chapter1 D/Activity1: onRestart--> 09-06 21:01:15.490 com.xk.chapter1 D/Activity1: onStart--> 09-06 21:01:15.490 com.xk.chapter1 D/Activity1: onResume--> 09-06 21:01:15.890 com.xk.chapter1 D/Activity2: onStop--> 09-06 21:01:15.890 com.xk.chapter1 D/Activity2: onDestroy-->
onStop可以做一些稍微重量級的操作旋讹,不過也別太耗時
onDestory中可以做資源的釋放等操作
彈出一個新的Activity瑰钮,舊的會調(diào)onPause->onStop冒滩,特殊的,如果新的Activity是透明主題浪谴,那么舊的Activity不會調(diào)用onStop开睡,因為它僅僅是失去了焦點,無法交互苟耻,還是可見的
onStart篇恒、onStop是從是否可見角度來說的,onPause和onResume是從是否位于前臺(可交互)角度來說的凶杖,除此之外沒啥區(qū)別胁艰。注意第一條。。蝗茁。
啟動Activity的請求由Instrumentation來處理醋虏,它通過Binder向AMS發(fā)送請求,AMS內(nèi)部維護(hù)著一個ActivityStack并且負(fù)責(zé)棧內(nèi)Activity的狀態(tài)同步哮翘,AMS通過ActivityThread去同步Activity的狀態(tài)颈嚼,從而完成生命周期的回調(diào)
異常情況下的生命周期
資源相關(guān)的系統(tǒng)配置發(fā)生改變導(dǎo)致Activity被殺死并重新創(chuàng)建
比如橫屏和豎屏?xí)褂貌煌馁Y源文件,如果屏幕方向發(fā)生改變饭寺,activity就會被銷毀重建阻课,除非我們指定不要讓他銷毀重建。當(dāng)然艰匙,這種銷毀重建會調(diào)用onSaveInstanceState來保存activity的狀態(tài)限煞,重建的時候會調(diào)用onRestoreInstanceState來恢復(fù)(onSaveInstanceState保存的數(shù)據(jù),在onCreate和onRestoreInstanceState中可以拿到)
onRestoreInstanceState會在onStart之前調(diào)用
activity被意外終止的時候员凝,activity會調(diào)用onSaveInstanceState署驻,然后委托window,接著window委托他內(nèi)部的view健霹,也就是頂層View(一般是DecorView)旺上,然后DecorView委托子View。糖埋。宣吱。一直往下到每一個View。每個View都有onSaveInstanceState和onRestoreInstanceState方法的瞳别。這種機制類似于事件分發(fā)機制
onSaveInstanceState只有在activity即將被被銷毀征候,并且有機會重建的時候才會被調(diào)用。簡單理解為就是異常終止祟敛,并且會馬上重建疤坝,對比按返回鍵銷毀和旋轉(zhuǎn)屏幕銷毀就好理解了。actvity銷毀后保存的數(shù)據(jù)在onCreate和onRestoreInstanceState中都可以拿到馆铁,但是onCreate中需要做非空判斷跑揉,onRestoreInstanceState不需要,因為onRestoreInstanceState一調(diào)用叼架,一定是有數(shù)據(jù)需要恢復(fù)了
按Home鍵或者啟動新Activity仍然會單獨觸發(fā)onSaveInstanceState的調(diào)用畔裕。因為Home之后或者新的activity出現(xiàn)之后衣撬,舊的activity到了后臺乖订,都有可能被殺。
資源內(nèi)存不足導(dǎo)致低優(yōu)先級Activity被殺
activity的優(yōu)先級
- 前臺Activity
- 可見但非前臺具练,比如彈出dialog乍构,我的理解是onPause之后的,不過不一定對,有待探究
- 后臺Activity哥遮,我的理解是onStop之后的岂丘,任玉剛書中說的是暫停后的,感覺有歧義眠饮,不太確定奥帘,有待探究
如果一個進(jìn)程中沒有四大組件在執(zhí)行,很快會被殺仪召,所以后臺任務(wù)一般要在service中運行寨蹋。我的理解是,如果在activity中開一個線程去做后臺任務(wù)扔茅,activity不在前臺的時候就容易被殺已旧,比如回到桌面
如果不想在屏幕旋轉(zhuǎn)后重建activity可以在清單文件中指定configChanges屬性,orientation召娜、keyboardHidden运褪,API13之后還需要指定screenSize。去年學(xué)這塊就是死記玖瘸,其實現(xiàn)在看來秸讹,所有的config(具體查表)改變都會導(dǎo)致Activity重建,這里配置之后店读,被配置的選項改變不會使activity重建嗦枢,但會回調(diào)onConfigurationChange方法,通知我們改變了屯断,然后根據(jù)自己的需求做一些事情就好了文虏。
Activity的啟動模式
Activity的LaunchMode
當(dāng)一個任務(wù)棧中沒有activity的時候,這個棧就會被回收
幾種啟動模式:
standard
-
singleTop
棧頂復(fù)用殖演,當(dāng)被復(fù)用的時候氧秘,會調(diào)用onNewIntent,參數(shù)中可以取到啟動新activity攜帶的intent趴久,并且onCreate丸相、onStart不會被調(diào)用
-
singleTask
被啟動的activity查看是否存在他想要的任務(wù)棧,如果存在彼棍,就是那樣了灭忠。。座硕。不存在弛作,就創(chuàng)建任務(wù)棧(默認(rèn)跟啟動他的context一樣,可以通過taskaffinity指定)
singleInstance
adb shell dumpsys activity 查看棧信息
啟動一個activity的時候华匾,一般新的activity會在調(diào)用startactivity的context所在的任務(wù)棧中映琳,但是applicationcontext不存在于任務(wù)棧,所以需要為新的activity指定FLAG_ACTIVITY_NEW_TASK標(biāo)記,不明白為什么在清單文件中指定不行
TaskAffinity(任務(wù)相關(guān)性)可以指定一個activity所需的棧名(默認(rèn)為他的包名)萨西,他只能和singleTask和allowTaskRepareniting配合使用有鹿,其他情況無效
如果沒有指定TaskAffinity,新啟動的activity會繼承啟動他activity的棧(singleInstance會進(jìn)入新的棧谎脯,但是實驗發(fā)現(xiàn)葱跋,棧名是一樣的,不過不是一個對象源梭,相當(dāng)于創(chuàng)建一個新的棧名相同的棧)
allowTaskReparenting可以指明一個activity
onNewIntent被調(diào)用的那些情況下年局,onCreate、onStart不會被調(diào)用
Activity的flags
摘自Android開發(fā)藝術(shù)圖書勘誤:第1.2.2小節(jié)中咸产,Activity的Flags矢否,這一節(jié)的內(nèi)容直接翻譯了Android官方文檔(http://developer.android.com/guide/components/tasks-and-back-stack.html#TaskLaunchModes),但是經(jīng)過實例驗證脑溢,發(fā)現(xiàn)書中的描述不準(zhǔn)確(或者說官方文檔中的描述不準(zhǔn)確)僵朗,結(jié)論為:Flags并不能簡單地等同于啟動模式,這一塊內(nèi)容需要進(jìn)一步驗證屑彻。
IntentFilter的匹配規(guī)則
這個直接結(jié)合生活就很好理解了
action/data在intent中是set验庙,category是add,所以就知道前兩個是唯一的社牲,category是可以配多個的
-
action行為粪薛、動作
- 在清單文件中配置的時候,action表示“我可以干什么”搏恤,所以可以配置多個:我可以展示圖片违寿、我可以展示音頻
- 在代碼中指定意圖的時候只能指定一個action:我將要干什么,比如我要展示圖片熟空,或者我要播放音頻藤巢,則分別跳轉(zhuǎn)到相應(yīng)的activity,不能我又要播放音頻又要展示圖片
- 所以action就是清單文件中配置多個息罗,指定意圖的時候只能制定一個
-
category分類
- 在清單文件中配置的時候掂咒,配置我屬于什么什么,比如:我屬于默認(rèn)分類迈喉、運動類绍刮、戶外類、輪滑類等(注意挨摸,這里最好指明自己屬于默認(rèn)類孩革,這樣在查找的時候,別人都能找到)
- 在代碼中指定意圖的時候可以指定我要:運動類并且是戶外類油坝,或者輪滑類(注意嫉戚,系統(tǒng)會自動加上默認(rèn)類)
- 所以,代碼中指明的類別澈圈,一定要在清單文件中指明彬檀,比如一個activity屬于默認(rèn)分類、運動類瞬女、戶外類窍帝、輪滑類,在代碼中我可以直接找運動或者運動以及戶外诽偷,但是如果我要找游戲坤学,肯定是找不到了
- data數(shù)據(jù)形式
- 這個跟action類似,他是根據(jù)數(shù)據(jù)的規(guī)則來匹配的报慕,action是我要找到"可以干什么"的activity深浮,data是我要找到“可以接收該data”的activity
- data主要分為URI和mimeType兩部分,一個代表資源位置眠冈,一個代表資源類型
對于Service和BroadcastReceiver飞苇,這套匹配規(guī)則也適用,不過對于Service蜗顽,官方推薦使用顯示意圖
在使用隱式意圖的時候布卡,最好先做個判斷,判斷是否有可以匹配的activity雇盖,具體方法查就行了忿等;在清單文件中配置category的時候,最好配置上default崔挖,使得intent更容易匹配它贸街,因為每個intent都會默認(rèn)加上default