Activity生命周期:
情形1:正常情況下
onCreate:Activity正在被創(chuàng)建,可以做一些初始化工作
onRestart:Activity正在被重新啟動括细,當(dāng)前Activity從不可見重新變?yōu)榭梢姞顟B(tài)
onStart:Activity正在被啟動,此時Activity已經(jīng)可見敷存,但還未出現(xiàn)在前臺慨蛙,無法與用戶交互
onResume:Activity可見梆掸,已經(jīng)處于前臺
onPause:Acticity正在停止瘪贱,用戶可見纱控,可以做一些存儲數(shù)據(jù)、停止動畫等工作菜秦,但不可做耗時操作甜害,因為onPause執(zhí)行完,新的Activity的onResume才會執(zhí)行
onStop:Activity即將停止球昨,可做一些稍微重量級的回收工作尔店,同樣不可太耗時
onDestory:Activity即將被銷毀,可以做一些回收工作和資源的釋放
onCreate和onDestory配對,標識Activity的創(chuàng)建與銷毀嚣州,僅調(diào)用一次
從Activity是否可見來說鲫售,onStart和onStop配對
從Activity是否來到前臺,onResume和onPause配對
Activity第一次啟動:onCreate->onStart->onResume该肴。Activity切換到后臺( 用戶打開新的Activity或者切換到桌面) 情竹,onPause->onStop(如果新Activity采用了透明主題,則當(dāng)前Activity不會回調(diào)onstop)沙庐。Activity從后臺到前臺,重新可見佳吞,onRestart->onStart->onResume拱雏。用戶退出Activity,onPause->onStop->onDestroy底扳。onStart開始到onStop之前铸抑,Activity可見。onResume到onPause之前衷模,Activity可以接受用戶交互鹊汛。在新Activity啟動之前,棧頂?shù)腁ctivity需要先onPause后阱冶,新Activity才能啟動刁憋。所以不能在onPause執(zhí)行耗時操作。onstop中也不可以太耗時木蹬,資源回收和釋放可以放在onDestroy中至耻。
情形2:異常情況下
在異常情況下系統(tǒng)會在onStop之前調(diào)用onSaveInstanceState來保存狀態(tài)。Activity重新創(chuàng)建后镊叁,會在onStart之后調(diào)用onRestoreInstanceState來恢復(fù)之前保存的數(shù)據(jù)尘颓。
系統(tǒng)只在Activity異常終止的時候才會調(diào)用 onSaveInstanceState 和onRestoreInstanceState 方法。其他情況不會觸發(fā)晦譬。
1疤苹、資源相關(guān)的系統(tǒng)配置發(fā)生改變導(dǎo)致Activity被殺死并重新創(chuàng)建
2、資源內(nèi)存不足導(dǎo)致低優(yōu)先級的Activity被殺死
三種Activity優(yōu)先級:前臺- 可見非前臺 -后臺敛腌,從高到低卧土。
如果一個進程沒有四大組件,那么將很快被系統(tǒng)殺死像樊。因此夸溶,后臺工作最好放入service中。
android:configChanges="orientation" 在manifest中指定 configChanges 在系統(tǒng)配置變化后不重新創(chuàng)建Activity凶硅,也不會執(zhí)行 onSaveInstanceState 和onRestoreInstanceState 方法缝裁,而是調(diào)用 onConfigurationChnaged 方法。
configChanges 一般常用三個選項:
1. locale 系統(tǒng)語言變化
2. keyborardHidden 鍵盤的可訪問性發(fā)生了變化,比如用戶調(diào)出了鍵盤
3. orientation 屏幕方向變化
Activity的啟動模式:
1. standard
每次啟動都會重新創(chuàng)建一個實例,不管這個Activity在棧中是否已經(jīng)存在壳贪。誰啟動了這個Activity绰咽,那么Activity就運行在啟動它的那個Activity所在的棧中。
用Application去啟動Activity時會報錯段多,原因是非Activity的Context沒有任務(wù)棧。解決辦法是為待啟動Activity制定FLAG_ACTIVITY_NEW_TASH標志位壮吩,這樣就會為它創(chuàng)建一個新的任務(wù)棧进苍。
2. singleTop 棧頂復(fù)用
如果新Activity位于任務(wù)棧的棧頂,那么此Activity不會被重新創(chuàng)建鸭叙,同時回調(diào) onNewIntent 方法觉啊。onCreate和onStart方法不會被執(zhí)行。
3. singleTask 棧內(nèi)復(fù)用
這是一種單實例模式沈贝。如果不存在activity所需要的任務(wù)棧杠人,則創(chuàng)建一個新任務(wù)棧和新Activity實例;如果存在所需要的任務(wù)棧宋下,不存在實例嗡善,則新創(chuàng)建一個Activity實例;如果存在所需要的任務(wù)棧和實例学歧,則不創(chuàng)建罩引,調(diào)用onNewIntent方法。同時使該Activity實例之上的所有Activity出棧枝笨。
[參考:taskAffinity標識Activity所需要的任務(wù)棧](https://gold.xitu.io/entry/57ac05858ac247005fec2ca1)
4. singleIntance 單實例模式
單實例模式蜒程。具有singleTask模式的所有特性,同時具有此模式的Activity只能獨自位于一個任務(wù)棧中伺帘。
假設(shè)兩個任務(wù)棧昭躺,前臺任務(wù)棧為12,后臺任務(wù)棧為XY伪嫁。Y的啟動模式是singleTask×祆牛現(xiàn)在請求Y,整個后臺任務(wù)棧會被切換到前臺张咳。如圖所示:
設(shè)置啟動模式
1. manifest中 設(shè)置下的 android:launchMode 屬性帝洪。
2. 啟動Activity的 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 。
3. 兩種同時存在時脚猾,以第二種為準葱峡。第一種方式無法直接為Activity添加FLAG_ACTIVITY_CLEAR_TOP標識,第二種方式無法指定singleInstance模式龙助。
4. 可以通過命令行 adb shell dumpsys activity 命令查看棧中的Activity信息砰奕。
Activity的Flags:
這些FLAG可以設(shè)定啟動模式、可以影響Activity的運行狀態(tài)。
- FLAG_ACTIVITY_NEW_TASK
? 為Activity指定“singleTask”啟動模式军援。
- FLAG_ACTIVITY_SINGLE_TOP
? 為Activity指定“singleTop"啟動模式仅淑。
- FLAG_ACTIVITY_CLEAR_TOP
? 具有此標記位的Activity啟動時,同一個任務(wù)棧中位于它上面的Activity都要出棧胸哥,一般和 ? ? ?? FLAG_ACTIVITY_NEW_TASK配合使用涯竟。
- FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
? 如果設(shè)置,新的Activity不會在最近啟動的Activity的列表(就是安卓手機里顯示最近打開的Activity那個系統(tǒng)級的UI)中保存空厌。等同于在xml中指定android:exludeFromRecents="true"屬性庐船。
IntentFilter的匹配規(guī)則
Activity調(diào)用方式
1. 顯示調(diào)用 明確指定被啟動對象的組件信息,包括包名和類名
2. 隱式調(diào)用 不需要明確指定組件信息嘲更,需要Intent能夠匹配目標組件中的IntentFilter中所設(shè)置的過濾信息筐钟。
匹配規(guī)則
- IntentFilter中的過濾信息有action、category哮内、data盗棵。
- 只有一個Intent同時匹配action類別壮韭、category類別北发、data類別才能成功啟動目標Activity。
- 一個Activity可以有多個intent-filter喷屋,一個Intent只要能匹配任何一組intent-filter即可成功啟動對應(yīng)的Activity琳拨。
** action**
action是一個字符串,匹配是指與action的字符串完全一樣,區(qū)分大小寫。
一個intent-filter可以有多個aciton屯曹,只要Intent中的action能夠和任何一個action相同即可成功匹配狱庇。
Intent中如果沒有指定action,那么匹配失敗恶耽。
** category**
category是一個字符串密任。
Intent可以沒有category,但是如果你一旦有category偷俭,不管有幾個浪讳,每個都必須與intent-filter中的其中一個category相同。
系統(tǒng)在 startActivity 和 startActivityForResult 的時候涌萤,會默認為Intent加上 android.intent.category.DEFAULT 這個category淹遵,所以為了我們的activity能夠接收隱式調(diào)用,就必須在intent-filter中加上 android.intent.category.DEFAULT 這個category负溪。
** data**
data的匹配規(guī)則與action一樣透揣,如果intent-filter中定義了data,那么Intent中必須要定義可匹配的data川抡。
intent-filter中data的語法:
? ? ? ? <data android:scheme="string"
? ? ? ? ? ? ? ? ? android:host="string"
? ? ? ? ? ? ? ? ? android:port="string"
? ? ? ? ? ? ? ? ? android:path="string"
? ? ? ? ? ? ? ? ? android:pathPattern="string"
? ? ? ? ? ? ? ? ? android:pathPrefix="string"
? ? ? ? ? ? ? ? ? android:mimeType="string"/>
Intent中的data有兩部分組成:mimeType和URI辐真。mimeType是指媒體類型,比如
image/jpeg、audio/mpeg4-generic和video/等拆祈,可以表示圖片恨闪、文本、視頻等不同的媒
體格式放坏。
URI的結(jié)構(gòu):
? ? ? ? <scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
實際例子
? ? ? ? content://com.example.project:200/folder/subfolder/etc
? ? ? ? http://www.baidu.com:80/search/info
scheme:URI的模式咙咽,比如http、file淤年、content等钧敞,默認值是 file 。
host:URI的主機名
port:URI的端口號
path麸粮、pathPattern和pathPrefix:這三個參數(shù)描述路徑信息溉苛。
path、pathPattern可以表示完整的路徑信息弄诲,其中pathPattern可以包含通配符 * 愚战,表示0個或者多個任意字符。
pathPrefix只表示路徑的前綴信息齐遵。
過濾規(guī)則的uri為空時寂玲,有默認值content和file,因此intent設(shè)置uri的scheme部分必須為content或file梗摇。
Intent指定data時拓哟,必須調(diào)用 setDataAndType 方法, setData 和 setType 會清除另一方的值伶授。
對于service和BroadcastReceiver也是同樣的匹配規(guī)則断序,不過對于service最好使用顯式調(diào)用。
隱式調(diào)用需注意
- 當(dāng)通過隱式調(diào)用啟動Activity時糜烹,沒找到對應(yīng)的Activity系統(tǒng)就會拋出 android.content.ActivityNotFoundException 異常违诗,所以需要判斷是否有Activity能夠匹配我們的隱式Intent。
- 采用 PackageManager 的 resloveActivity 方法或Intent 的 resloveActivity 方法
? ? ? ? public abstract List<ResolveInfo> queryIntentActivityies(Intent intent,int flags);
? ? ? ? public abstract ResolveInfo resloveActivity(Intent intent,int flags);
以上的第二個參數(shù)使用 MATCH_DEFAULT_ONLY 疮蹦,這個標志位的含義是僅僅匹配那些在
intent-filter中聲明了 android.intent.category.DEFAULT 這個category的Activity诸迟。因為如果把不含這個category的Activity匹配出來了,由于不含DEFAULT這個category的Activity是無法接受隱式Intent的從而導(dǎo)致startActivity失敗挚币。
- 下面的action和category用來表明這是一個入口Activity亮蒋,并且會出現(xiàn)在系統(tǒng)的應(yīng)用列表中,二者缺一不可妆毕。
? ? ? ? <action android:name="android.intent.action.MAIN" />
? ? ? ? <category android:name="android.intent.category.LAUNCHER" />