一. activity生命周期
按照慣例槽奕,先上張 Activity 生命周期圖
回答一個問題: Activity是什么桐绒?
Activity表示為具有用戶界面的單一屏幕产捞,可理解為"界面"超埋。正常情況下昙篙,除了Window秘豹、Dialog和Toast携御,我們能見到的界面的確只有Activity。
1.1 activity生命周期分析
1.1.1 生命周期概述
onCreate ()
必須實現此回調既绕,該回調在系統(tǒng)創(chuàng)建Activity時被觸發(fā)啄刹。在這個方法中,應該初始化一些基本組件凄贩,例如創(chuàng)建視圖并進行數據綁定等誓军。最重要的是,調用 setContentView() 去加載界面布局資源疲扎。
另外昵时,當 onCreate () 完成后,接下來的回調永遠是 onStart ()椒丧。onStart ()
Activity 進入 "已啟動" 狀態(tài)壹甥,并且對用戶可見。但是還沒有出現在前臺壶熏,也不能用戶進行交互句柠,這個回調做了最后的一些準備工作。onResume ()
可見棒假、出現在前臺溯职、可交互。 系統(tǒng)在Activity開始與用戶進行交互之前調用此回調帽哑。此時谜酒,Activity位于activity堆棧的頂部,并捕獲用戶的所有輸入妻枕。
onPause () 回調總是跟在 onResume ()之后僻族。onPause ()
當 activity 失去焦點并進入暫停狀態(tài)時粘驰,系統(tǒng)會調用。 例如鹰贵,當用戶點擊 "后退" 或 "最近" 按鈕時晴氨,會出現此狀態(tài)。
當系統(tǒng)調用 onPause () 時碉输,從技術上講,Activity仍然是部分可見的亭珍,但通常表示用戶正在離開Activity敷钾,Activity 將很快進入 Stopped 或者 Resumed 狀態(tài)。
如果用戶期望 UI 更新肄梨,則處于 Paused 狀態(tài)的 Activity 可以繼續(xù)更新 UI阻荒。 例如 導航地圖屏幕或媒體播放器播放,即使它們失去了焦點众羡,用戶也希望他們的 UI 繼續(xù)更新侨赡。
你不應該在 onPause 里去保存 應用程序或用戶數據,進行網絡調用粱侣,或執(zhí)行數據庫事務等耗重量級操作羊壹。
一旦 onPause() 執(zhí)行完畢,接下來的回調將 onStop() 或 onResume()齐婴,根據活動進入暫停狀態(tài)以后會發(fā)生什么決定油猫。onStop ()
當 activity 不再對用戶可見時,系統(tǒng)會調用柠偶。 這可能是因為 activity 被破壞情妖,或者新 activity 正在開始,又或者 一個存在的activity正在進入 Resumed 狀態(tài)并且正在覆蓋已停止的 activity诱担。
如果這個 activity 準備返回和用戶進行交互毡证,則會回調 onRestart()。
如果這個 activity 完全終止蔫仙,則會回調 onDestroy()
onRestart ()
當處于 "Stopped" 狀態(tài)的 activity 即將重新啟動時料睛,系統(tǒng)會調用此方法。 onRestart()會還原 activity 在 stopped時的狀態(tài)數據匀哄。onDestroy ()
系統(tǒng)在activity 銷毀之前調用此回調秦效。
此回調是activity 收到的最后一個回調。在這里涎嚼,可以做一些回收工作和最終的資源釋放阱州。
1.1.2 生命周期具體說明
針對一個Activity,第一次啟動法梯,回調如下:onCreate -> onStart -> onResume苔货。
當用戶打開新的 activity 或者切換到桌面 或者按最近按鈕時犀概,回調如下:onPause -> onStop。
特殊情況, 如果新Activity采用透明主題時夜惭,回調如下:onPause姻灶。當用戶再次回到原 activity 時,回調如下:onRestart -> onStart -> onResume诈茧。
當用戶彈出一個對話框( AlertDialog )時产喉,activity 生命周期不會發(fā)生變化。
當用戶按back回退時敢会,回調如下:onPause -> onStop ->onDestroy曾沈。
問題:當前Activity 為A, 此時用戶打開一個新的Activity B鸥昏,那么 B 的 onResume 和 A 的 onPause 哪個先執(zhí)行?
- 可自己動手試一試塞俱,答案是 舊 Activity A 先 onPause,然后 新 Activity B 再啟動吏垮。其實很好理解障涯,onResume代表著可見、可交互膳汪,如果舊的 Activity 不先 onPause唯蝶,那豈不是會出現兩個可見、可交互的界面旅敷,不就亂套了生棍。
- 看源碼更能加深理解。
1.2 activity狀態(tài)
只有三個狀態(tài)是靜態(tài)的媳谁,可以存在較長時間保持狀態(tài)不變涂滴。(其他狀態(tài)只是過渡狀態(tài),系統(tǒng)快速切換并切換到下一狀態(tài))
-
運行(Resumed)
- 當前 activity 處于棧頂晴音,用戶可以與它進行交互柔纵。(通常也被理解為 "running" 狀態(tài))
- 此狀態(tài)由 onResume() 進入,onPause() 退出
-
暫停(Paused)
- 當前 activity 仍然是可見的锤躁,但被另一個 activity 處在最上方搁料,最上方的 activity 是半透明的,或者是部分覆蓋整個屏幕系羞。被暫停的 activity 不會再接收用戶的輸入郭计。
- 處于活著的狀態(tài) (Activity 對象存留在內存,保持著所有的 狀態(tài)和成員信息椒振,仍然吸附在 window manager)昭伸。
- 當資源內存極度不足時,系統(tǒng)會殺掉該 activity 釋放相應資源澎迎。
- 此狀態(tài)由 onPaues() 進入庐杨,退出可能是從 onResume() 重新喚醒軟件选调,或者被 onStop() 殺掉。
-
停止(Stopped)
- 當前 activity 完全被隱藏灵份,不被用戶可見仁堪,可以認為是處于后臺。
- 處于活著的狀態(tài) (Activity 對象存留在內存填渠,保持著所有的 狀態(tài)和成員信息弦聂,不再吸附在 window manager)。
- 由于對用戶不再可見氛什,只要有內存的需要横浑,系統(tǒng)會殺掉該 activity 來釋放相應資源。
- 此狀態(tài)由 onStop() 進入屉更,退出是從 onRestart() 重新喚醒軟件,或者被 onDestroy() 徹底死亡洒缀。其他狀態(tài)(Created與 Started )都是短暫的瑰谜,系統(tǒng)快速執(zhí)行那些回調函數并通過。
1.3 android進程優(yōu)先級
前臺進程
一般情況是树绩,在前臺與用戶進行交互的 activity萨脑,或與前臺進程 綁定的 service。可見進程
處于 paused 狀態(tài)饺饭,用戶可見渤早,但是不能進行交互。服務進程
如果一個進程中運行著 service瘫俊,這個service 是通過 startService() 開啟的鹊杖,并且不屬于上面兩種高優(yōu)先級的情況,那它就是一個服務進程扛芽。后臺進程
處于 stopped 狀態(tài)骂蓖。空進程
如果一個進程不包含任何活躍的應用組件,則認為是空進程川尖。
二. android任務棧
任務棧是一種“后進先出”的棧結構登下。
任務棧分為 前臺任務棧 和 后臺任務棧 ,后臺任務棧中的 activity 位于暫停狀態(tài)叮喳。
- TaskAffinity 任務相關性被芳, 這個參數標識了一個 Activity 所需要的任務棧的名字。
- 默認情況下馍悟,所有 Activity 所需的任務棧的名字為包名畔濒。
- 通過指定 TaskAffinity 可以為 Activity 指定新的任務棧的名字,當然必須不能和包名相同赋朦。
- TaskAfiinity 主要是和 singleTask 啟動模式或者 allowTaskReparenting 屬性配對使用篓冲。
- 在 AndroidManifest 文件中指定李破。
- 命令** adb shell dumpsys activity** 可導出 Activity 信息。
三. activity啟動模式
standard(標準模式)
系統(tǒng)默認模式壹将,每啟動一個 Activity 就會重新創(chuàng)建一個新的實例嗤攻。
這種模式下, Activity A 啟動了 Activity B诽俯,那么 B 就會進入到 A 所在的任務棧中妇菱。singleTop(棧頂復用模式)
如果新 Activity 已經位于棧頂,那么此 Activity 不會再重新創(chuàng)建暴区,同時它的 onNewIntent 方法會被回調闯团。singleTask(棧內復用模式)
只要 Activity 在一個棧中存在,那么多次啟動此 Activity 都不會重新創(chuàng)建實例仙粱。singleInstance(單實例模式, 加強的 singleTask 模式)
除了具有 singleTask 模式的所有特性外房交,還加強了一點,那就是具有此種模式的 Activity 只能單獨的位于一個任務棧中伐割。
例1:
任務棧(com.yjnull.slowdev4android)有個 ExampleActivity 候味,啟動模式為standard。
任務棧(com.yy.task1)有個 ThreeActivity隔心,啟動模式為 singleInstance白群。
啟動ExampleActivity,然后啟動ThreeActivity硬霍,然后兩個互相啟動帜慢,任務棧如下截圖。
例2:
四. IntentFilter 的匹配規(guī)則
隱式啟動 Activity 需要 Intent 能夠匹配目標組件的 IntentFilter中所設置的過濾信息唯卖,如果不匹配則無法啟動目標組件粱玲。
IntentFilter 的過濾信息有 action、category耐床、data
action:
1.action是一個字符串 區(qū)分大小寫
2.當過濾規(guī)則中有 action 時密幔,那么只要 Intent 中的 action 能夠和過濾規(guī)則中的任何一個相同即可匹配成功。需注意:如果Intent 沒有指定 action撩轰,將匹配失敗胯甩。
3.也就是說,當過濾規(guī)則有 action 時堪嫂,Intent 中必須存在 action偎箫。category:
1.category 和 action 不同,它不強制要求 Intent 中必須含有 category皆串。
2.如果 Intent 中沒有 category淹办,那么可以匹配成功。
3.如果 Intent 中有 category恶复,那么不管有幾個 category怜森,都必須和過濾規(guī)則中的 category 相同才能匹配成功速挑。
4.為什么不設置 category 也可以匹配成功,因為 startActivity 時會默認為 Intent 加上 "android.intent.category.DEFAULT" 這個 category副硅。
5.所以為了 activity 能夠接收隱式調用姥宝,必須在intent-filter 中指定 "android.intent.category.DEFAULT" 這個 category。data
1.data 由兩部分組成:mimeType 和 URI恐疲。
2.mimeType 指媒體類型:如 image/jpeg腊满、video/*等。
3.URI 結構:
<schema>://<host>:<port>/[<path>|<pathPrefit>|<pathPattern>]
4.如果沒有指定 URI 培己,則 URI 的默認值為 content 或 file
5.例如指定 mimeType 為 image/png碳蛋,未指定 URI 。 則如下代碼可匹配過濾規(guī)則
intent.setDataAndType(Uri.parse("file://abc"), "image/png");
或者
intent.setDataAndType(Uri.parse("content://abc"), "image/png");
總結
1.隱式啟動 Activity 時省咨,IntentFilter 一定要指定 "android.intent.category.DEFAULT" 這個 category肃弟。
2.action、category零蓉、data ,如果匹配了 action愕乎,那么其余兩個也得匹配成功才能找到 Activity。
3.如果只匹配 data壁公,那么 action 不指定也可以運行成功,不會返回指定 Activity绅项,而是返回ResolverActivity紊册,讓你選擇默認程序運行。
參考
http://gityuan.com/
Android 開發(fā)藝術探索