前言
- 學(xué)
Android
有一段時(shí)間了,一直都只顧著學(xué)新的東西鸟款,最近發(fā)現(xiàn)很多平常用的少的東西竟讓都忘了膏燃,趁著這兩天,打算把有關(guān)Activity
的內(nèi)容以問(wèn)題的形式梳理出來(lái)何什,也供大家查缺補(bǔ)漏组哩。
本文中,我將一改往日寫博客的習(xí)慣富俄,全文用 XMind 將所有知識(shí)點(diǎn)以思維導(dǎo)圖的形式呈現(xiàn)禁炒,歡迎大家食用~~
文章目錄
方便大家學(xué)習(xí),我在 GitHub 上建立個(gè) 倉(cāng)庫(kù)
倉(cāng)庫(kù)內(nèi)容與博客同步更新霍比。由于我在
稀土掘金
簡(jiǎn)書(shū)
CSDN
博客園
等站點(diǎn)幕袱,都有新內(nèi)容發(fā)布。所以大家可以直接關(guān)注該倉(cāng)庫(kù)悠瞬,以免錯(cuò)過(guò)精彩內(nèi)容们豌!倉(cāng)庫(kù)地址:
超級(jí)干貨!精心歸納Android
浅妆、JVM
望迎、算法等,各位帥氣的老鐵支持一下凌外!給個(gè) Star 辩尊!
神圖
- 在開(kāi)始之前,先讓我們看看
Android
的activity
到底都有哪些東西康辑? - 借一張網(wǎng)上很火的圖帶你了解
Activity
一摄欲、 生命周期
- 先貼一張聞名遐邇的圖
- 我們生命周期先看看具體有哪些方法回調(diào),在逐一攻破:
[圖片上傳失敗...(image-76615c-1572405738902)]
1.1 Dialog 彈出時(shí)
- 如果是單純是創(chuàng)建的
dialog
疮薇,Activity
并不會(huì)執(zhí)行生命周期的方法 - 但是如果是跳轉(zhuǎn)到一個(gè)不是全屏的
Activity
的話, 當(dāng)然就是按照正常的生命周期來(lái)執(zhí)行了 - 即
onPasue()
->onPause()
( 不會(huì)執(zhí)行原Activity
的onStop()
, 否則上個(gè)頁(yè)面就不顯示了 )
1.2 橫豎屏切換時(shí)
不設(shè)置
Activity
的android:configChanges
時(shí)胸墙,切屏?xí)匦抡{(diào)用各個(gè)生命周期,切橫屏?xí)r會(huì)執(zhí)行一次按咒,切豎屏?xí)r會(huì)執(zhí)行兩次設(shè)置
Activity
的android:configChanges="orientation"
時(shí)迟隅,切屏還是會(huì)重新調(diào)用各個(gè)生命周期,切橫励七、豎屏?xí)r只會(huì)執(zhí)行一次設(shè)置
Activity
的android:configChanges="orientation|keyboardHidden"
時(shí)智袭,切屏不會(huì)重新調(diào)用各個(gè)生命周期,只會(huì)執(zhí)行onConfigurationChanged
方法注意:還有一點(diǎn)掠抬,非常重要补履,一個(gè)
Android
的變更細(xì)節(jié)!當(dāng)API >12
時(shí)剿另,需要加入screenSize
屬性箫锤,否則屏幕切換時(shí)即使你設(shè)置了orientation
系統(tǒng)也會(huì)重建Activity
贬蛙!
1.3 不同場(chǎng)景下 Activity 生命周期的變化過(guò)程
- 啟動(dòng)
Activity
:onCreate()
--->onStart()
--->onResume()
,Activity
進(jìn)入運(yùn)行狀態(tài)谚攒。 - 鎖屏?xí)r會(huì)執(zhí)行
onPause()
和onStop()
, 而開(kāi)屏?xí)r則應(yīng)該執(zhí)行onStart()
onResume()
-
Activity
退居后臺(tái): 當(dāng)前Activity
轉(zhuǎn)到新的Activity
界面或按Home
鍵回到主屏:onPause()
--->onStop()
阳准,進(jìn)入停滯狀態(tài)。 -
Activity
返回前臺(tái):onRestart()
--->onStart()
--->onResume()
馏臭,再次回到運(yùn)行狀態(tài)野蝇。 -
Activity
退居后臺(tái): 且系統(tǒng)內(nèi)存不足, 系統(tǒng)會(huì)殺死這個(gè)后臺(tái)狀態(tài)的Activity
括儒,若再次回到這個(gè)Activity
,則會(huì)走onCreate()
-->onStart()
--->onResume()
1.4 將一個(gè) Activity 設(shè)置成窗口的樣式
只需要給我們的 Activity
配置如下屬性即可绕沈。
android:theme="@android:style/Theme.Dialog"
1.5 退出已調(diào)用多個(gè) Activity 的 Application
- 通常情況用戶退出一個(gè)
Activity
只需按返回鍵,我們寫代碼想退出activity
直接調(diào)用finish()
方法就行固逗。
- 發(fā)送特定廣播:
- 在需要結(jié)束應(yīng)用時(shí), 發(fā)送一個(gè)特定的廣播,每個(gè)
Activity
收到廣播后,關(guān)閉 即可哈踱。 - 給某個(gè)
activity
注冊(cè)接受接受廣播的意圖registerReceiver(receiver, filter)
- 如果過(guò)接受到的是 關(guān)閉
activity
的廣播activity finish()
掉
- 遞歸退出
- 就調(diào)用
finish()
方法 把當(dāng)前的Activity
退出 - 在打開(kāi)新的
Activity
時(shí)使用startActivityForResult
, 然后自己加標(biāo)志, 在onActivityResult
中處理, 遞歸關(guān)閉。
- 其實(shí)
- 也可以通過(guò)
intent
的flag
來(lái)實(shí)現(xiàn)intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
激活一個(gè)新的activity
奋早。 - 此時(shí)如果該任務(wù)棧中已經(jīng)有該
Activity
, 那么系統(tǒng)會(huì)把這個(gè)Activity
上面的所有Activity
干掉姓建。 - 其實(shí)相當(dāng)于給
Activity
配置的啟動(dòng)模式為singleTask
屑柔。
- 記錄打開(kāi)的
Activity
- 每打開(kāi)一個(gè)
Activity
, 就記錄下來(lái)。 - 在需要退出時(shí) , 關(guān)閉每一個(gè)
Activity
1.6 鎖定屏與解鎖屏幕塌衰,Activity 如何執(zhí)行生命周期
- 鎖屏?xí)r會(huì)執(zhí)行
onPause()
和onStop()
, 而開(kāi)屏?xí)r則應(yīng)該執(zhí)行onStart()
onResume()
1.7 修改 Activity 進(jìn)入和退出動(dòng)畫(huà)
- 可以通過(guò)兩種方式 圃郊, 一是通過(guò)定義
Activity
的主題 价涝,二是通過(guò)覆寫Activity
的overridePendingTransition
方法。 - 通過(guò)設(shè)置主題樣式在
styles.xml
中編輯代碼 , 添加themes.xml
文件:在AndroidManifest.xml
中給指定的Activity
指定theme
持舆。 - 覆寫
overridePendingTransition
方法:overridePendingTransition(R.anim.fade, R.anim.hold)
;
1.8 Activity 的四種狀態(tài)
-
runnig
:用戶可以點(diǎn)擊色瘩,activity
處于棧頂狀態(tài)。 -
paused
:activity
失去焦點(diǎn)的時(shí)候逸寓,被一個(gè)非全屏的activity
占據(jù)或者被一個(gè)透明的activity
覆蓋居兆,這個(gè)狀態(tài)的activity
并沒(méi)有銷毀,它所有的狀態(tài)信息和成員變量仍然存在竹伸,只是不能夠被點(diǎn)擊泥栖。(內(nèi)存緊張的情況,這個(gè)activity
有可能被回收)
-
stopped
:這個(gè)activity
被另外一個(gè)activity
完全覆蓋勋篓,但是這個(gè)activity
的所有狀態(tài)信息和成員變量仍然存在(除了內(nèi)存緊張) -
killed
:這個(gè)activity
已經(jīng)被銷毀吧享,其所有的狀態(tài)信息和成員變量已經(jīng)不存在了栏账。
1.9 如何處理異常退出
-
Activity
異常退出的時(shí)候 -->onPause()
-->onSaveInstanceState()
-->onStop()
-->onDestory()
- 需要注意的是
onSaveInstanceState()
方法與onPause
并沒(méi)有嚴(yán)格的先后關(guān)系抢肛,有可能在onPause
之前术陶,也有可能在其后面調(diào)用健田,但會(huì)在onStop()
方法之前調(diào)用 - 異常退出后又重新啟動(dòng)該
Activity
-->onCreate()
-->onStart()
-->onRestoreInstanceState()
-->onResume()
- 搞懂這個(gè)生命周期的執(zhí)行后就可以回答了,首先要知道面試官的意思:是要重新啟動(dòng)并恢復(fù)這個(gè)
Activity
還是說(shuō)直接退出整個(gè)app
- 如果要恢復(fù)則要在
onSaveInstanceState()
中進(jìn)行保存數(shù)據(jù)并在onRestoreInstanceState()
中進(jìn)行恢復(fù) - 如果是要退出
app
的話就要捕獲全局的異常信息柿扣,并退出app
- 當(dāng)然個(gè)人建議是使用
UncaughtExceotionHandler
來(lái)捕獲全局異常進(jìn)行退出app
的操作钠至,這樣會(huì)減少之前崩潰所造成的后遺癥近哟!
1.10 什么是 onNewIntent
如果
IntentActivity
處于任務(wù)棧的頂端盐股,也就是說(shuō)之前打開(kāi)過(guò)的Activity
钱豁,現(xiàn)在處于onPause
耻卡、onStop
狀態(tài)的話疯汁,其他應(yīng)用再發(fā)送Intent
的話執(zhí)行順序?yàn)椋?code>onNewIntent,
onRestart
卵酪,onStart
幌蚊,onResume
谤碳。
二、 啟動(dòng)模式
2.1 啟動(dòng)模式
-
Activity
一共有四種launchMode
:standard
溢豆、singleTop
蜒简、singleTask
、singleInstance
漩仙。
-
Standard
模式(默認(rèn)模式)
說(shuō)明: 每次啟動(dòng)一個(gè)
Activity
都會(huì)又一次創(chuàng)建一個(gè)新的實(shí)例入棧搓茬,無(wú)論這個(gè)實(shí)例是否存在。生命周期:每次被創(chuàng)建的實(shí)例
Activity
的生命周期符合典型情況队他,它的onCreate
卷仑、onStart
、onResume
都會(huì)被調(diào)用麸折。舉例:此時(shí)
Activity
棧中以此有A
锡凝、B
、C
三個(gè)Activity
垢啼,此時(shí)C處于棧頂窜锯,啟動(dòng)模式為Standard
模式。若在C Activity
中加入點(diǎn)擊事件芭析,須要跳轉(zhuǎn)到還有一個(gè)同類型的C Activity
锚扎。結(jié)果是還有一個(gè)C Activity
進(jìn)入棧中,成為棧頂放刨。
-
SingleTop
模式(棧頂復(fù)用模式)
說(shuō)明:分兩種處理情況:須要?jiǎng)?chuàng)建的
Activity
已經(jīng)處于棧頂時(shí)工秩,此時(shí)會(huì)直接復(fù)用棧頂?shù)?Activity
。不會(huì)再創(chuàng)建新的Activity
进统;若須要?jiǎng)?chuàng)建的Activity
不處于棧頂助币,此時(shí)會(huì)又一次創(chuàng)建一個(gè)新的Activity
入棧,同Standard
模式一樣螟碎。生命周期:若情況一中棧頂?shù)?
Activity
被直接復(fù)用時(shí)眉菱,它的onCreate
、onStart
不會(huì)被系統(tǒng)調(diào)用掉分,由于它并沒(méi)有發(fā)生改變俭缓。可是一個(gè)新的方法onNewIntent
會(huì)被回調(diào)(Activity
被正常創(chuàng)建時(shí)不會(huì)回調(diào)此方法)酥郭。舉例:此時(shí)
Activity
棧中以此有A
华坦、B
、C
三個(gè)Activity
不从,此時(shí)C
處于棧頂惜姐,啟動(dòng)模式為SingleTop
模式。情況一:在C Activity
中加入點(diǎn)擊事件,須要跳轉(zhuǎn)到還有一個(gè)同類型的C Activity
歹袁。結(jié)果是直接復(fù)用棧頂?shù)?C Activity
坷衍。情況二:在C Activity
中加入點(diǎn)擊事件,須要跳轉(zhuǎn)到還有一個(gè)A Activity
条舔。結(jié)果是創(chuàng)建一個(gè)新的Activity
入棧枫耳。成為棧頂。
-
SingleTask
模式(棧內(nèi)復(fù)用模式)
說(shuō)明:若須要?jiǎng)?chuàng)建的
Activity
已經(jīng)處于棧中時(shí)孟抗,此時(shí)不會(huì)創(chuàng)建新的Activity
迁杨,而是將存在棧中的Activity
上面的其他Activity
所有銷毀,使它成為棧頂凄硼。如果是在別的應(yīng)用程序中啟動(dòng)它仑最,則會(huì)新建一個(gè)
task
,并在該task中啟動(dòng)這個(gè)Activity
帆喇,singleTask
允許別的Activity
與其在一個(gè)task
中共存警医,也就是說(shuō),如果我在這個(gè)singleTask
的實(shí)例中再打開(kāi)新的Activity
坯钦,這個(gè)新的Activity
還是會(huì)在singleTask
的實(shí)例的task
中预皇。生命周期:同
SingleTop
模式中的情況一同樣。僅僅會(huì)又一次回調(diào)Activity
中的onNewIntent
方法舉例:此時(shí)
Activity
棧中以此有A
婉刀、B
吟温、C
三個(gè)Activity
。此時(shí)C
處于棧頂突颊,啟動(dòng)模式為SingleTask
模式鲁豪。情況一:在C Activity
中加入點(diǎn)擊事件,須要跳轉(zhuǎn)到還有一個(gè)同類型的C Activity
律秃。結(jié)果是直接用棧頂?shù)?C Activity
爬橡。情況二:在C Activity
中加入點(diǎn)擊事件,須要跳轉(zhuǎn)到還有一個(gè)A Activity
棒动。結(jié)果是將A Activity
上面的B
糙申、C
所有銷毀,使A Activity
成為棧頂船惨。
-
SingleInstance
模式(單實(shí)例模式)
說(shuō)明:
SingleInstance
比較特殊柜裸,是全局單例模式,是一種加強(qiáng)的SingleTask
模式粱锐。它除了具有它所有特性外疙挺,還加強(qiáng)了一點(diǎn):只有一個(gè)實(shí)例,并且這個(gè)實(shí)例獨(dú)立運(yùn)行在一個(gè)task
中怜浅,這個(gè)task
只有這個(gè)實(shí)例铐然,不允許有別的Activity
存在。這個(gè)經(jīng)常使用于系統(tǒng)中的應(yīng)用,比如
Launch
锦爵、鎖屏鍵的應(yīng)用等等,整個(gè)系統(tǒng)中僅僅有一個(gè)奥裸!所以在我們的應(yīng)用中一般不會(huì)用到险掀。了解就可以。舉例:比方
A Activity
是該模式湾宙,啟動(dòng)A
后樟氢。系統(tǒng)會(huì)為它創(chuàng)建一個(gè)單獨(dú)的任務(wù)棧,由于棧內(nèi)復(fù)用的特性侠鳄。興許的請(qǐng)求均不會(huì)創(chuàng)建新的Activity
埠啃,除非這個(gè)獨(dú)特的任務(wù)棧被系統(tǒng)銷毀。
2.2 啟動(dòng)模式的使用方式
- 在
Manifest.xml
中指定Activity
啟動(dòng)模式
- 一種靜態(tài)的指定方法
- 在
Manifest.xml
文件里聲明Activity
的同一時(shí)候指定它的啟動(dòng)模式 - 這樣在代碼中跳轉(zhuǎn)時(shí)會(huì)依照指定的模式來(lái)創(chuàng)建
Activity
伟恶。
- 啟動(dòng)
Activity
時(shí)碴开。在Intent
中指定啟動(dòng)模式去創(chuàng)建Activity
- 一種動(dòng)態(tài)的啟動(dòng)模式
- 在
new
一個(gè)Intent
后 - 通過(guò)
Intent
的addFlags
方法去動(dòng)態(tài)指定一個(gè)啟動(dòng)模式。
- 注意:以上兩種方式都能夠?yàn)?
Activity
指定啟動(dòng)模式博秫,可是二者還是有差別的潦牛。
優(yōu)先級(jí):動(dòng)態(tài)指定方式即另外一種比第一種優(yōu)先級(jí)要高,若兩者同一時(shí)候存在挡育,以另外一種方式為準(zhǔn)巴碗。
限定范圍:第一種方式無(wú)法為
Activity
直接指定FLAG_ACTIVITY_CLEAR_TOP
標(biāo)識(shí),另外一種方式無(wú)法為Activity
指定singleInstance
模式即寒。
2.3 啟動(dòng)模式的實(shí)際應(yīng)用場(chǎng)景
這四種模式中的
Standard
模式是最普通的一種橡淆,沒(méi)有什么特別注意。而SingleInstance
模式是整個(gè)系統(tǒng)的單例模式母赵,在我們的應(yīng)用中一般不會(huì)應(yīng)用到逸爵。所以,這里就具體解說(shuō)SingleTop
和SingleTask
模式的運(yùn)用場(chǎng)景:
-
SingleTask
模式的運(yùn)用場(chǎng)景
- 最常見(jiàn)的應(yīng)用場(chǎng)景就是保持我們應(yīng)用開(kāi)啟后僅僅有一個(gè)
Activity
的實(shí)例凹嘲。 - 最典型的樣例就是應(yīng)用中展示的主頁(yè)(
Home
頁(yè))痊银。 - 假設(shè)用戶在主頁(yè)跳轉(zhuǎn)到其他頁(yè)面,運(yùn)行多次操作后想返回到主頁(yè)施绎,假設(shè)不使用
SingleTask
模式溯革,在點(diǎn)擊返回的過(guò)程中會(huì)多次看到主頁(yè),這明顯就是設(shè)計(jì)不合理了谷醉。
-
SingleTop
模式的運(yùn)用場(chǎng)景
- 假設(shè)你在當(dāng)前的
Activity
中又要啟動(dòng)同類型的Activity
- 此時(shí)建議將此類型
Activity
的啟動(dòng)模式指定為SingleTop
致稀,能夠降低Activity的創(chuàng)建,節(jié)省內(nèi)存俱尼!
- 注意:復(fù)用
Activity
時(shí)的生命周期回調(diào)
- 這里還須要考慮一個(gè)
Activity
跳轉(zhuǎn)時(shí)攜帶頁(yè)面參數(shù)的問(wèn)題抖单。 - 由于當(dāng)一個(gè)
Activity
設(shè)置了SingleTop
或者SingleTask
模式后,跳轉(zhuǎn)此Activity
出現(xiàn)復(fù)用原有Activity
的情況時(shí),此Activity
的onCreate
方法將不會(huì)再次運(yùn)行矛绘。onCreate
方法僅僅會(huì)在第一次創(chuàng)建Activity
時(shí)被運(yùn)行耍休。 - 而一般
onCreate
方法中會(huì)進(jìn)行該頁(yè)面的數(shù)據(jù)初始化、UI
初始化货矮,假設(shè)頁(yè)面的展示數(shù)據(jù)無(wú)關(guān)頁(yè)面跳轉(zhuǎn)傳遞的參數(shù)羊精,則不必操心此問(wèn)題 - 若頁(yè)面展示的數(shù)據(jù)就是通過(guò)
getInten()
方法來(lái)獲取,那么問(wèn)題就會(huì)出現(xiàn):getInten()
獲取的一直都是老數(shù)據(jù)囚玫,根本無(wú)法接收跳轉(zhuǎn)時(shí)傳送的新數(shù)據(jù)喧锦!
- 以下,通過(guò)一個(gè)樣例來(lái)具體解釋:
以上代碼中的
CourseDetailActivity
在配置文件里設(shè)置了啟動(dòng)模式是SingleTop
模式抓督,依據(jù)上面啟動(dòng)模式的介紹可得知燃少,當(dāng)CourseDetailActivity
處于棧頂時(shí)。再次跳轉(zhuǎn)頁(yè)面到
CourseDetailActivity
時(shí)會(huì)直接復(fù)用原有的Activity
铃在,并且此頁(yè)面須要展示的數(shù)據(jù)是從getIntent()
方法得來(lái)阵具,可是initData()
方法不會(huì)再次被調(diào)用,此時(shí)頁(yè)面就無(wú)法顯示新的數(shù)據(jù)定铜。當(dāng)然這樣的情況系統(tǒng)早就為我們想過(guò)了怔昨,這時(shí)我們須要另外一個(gè)回調(diào)
onNewIntent(Intent intent)
方法。此方法會(huì)傳入最新的intent
宿稀,這樣我們就能夠解決上述問(wèn)題趁舀。這里建議的方法是又一次去setIntent
。然后又一次去初始化數(shù)據(jù)和UI
祝沸。代碼例如以下所看到的:
- 這樣矮烹,在一個(gè)頁(yè)面中能夠反復(fù)跳轉(zhuǎn)并顯示不同的內(nèi)容。
2.4 快速啟動(dòng)一個(gè) Activity
- 這個(gè)問(wèn)題其實(shí)也是比較簡(jiǎn)單的罩锐,就是不要在
Activity
的onCreate
方法中執(zhí)行過(guò)多繁重的操作奉狈,并且在onPasue
方法中同樣不能做過(guò)多的耗時(shí)操作。
2.5 啟動(dòng)流程
注意涩惑!這里并不是要回答
Activity
的生命周期仁期!
2.6 Activity 的 Flags
標(biāo)記位既能夠設(shè)定Activity的啟動(dòng)模式,如同上面介紹的竭恬,在動(dòng)態(tài)指定啟動(dòng)模式跛蛋,比方
FLAG_ACTIVITY_NEW_TASK
和FLAG_ACTIVITY_SINGLE_TOP
等。它還能夠影響Activity
的運(yùn)行狀態(tài) 痊硕,比方FLAG_ACTIVITY_CLEAN_TOP
和FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
等赊级。以下介紹幾個(gè)基本的標(biāo)記位,切勿死記岔绸,理解幾個(gè)就可以理逊,須要時(shí)再查官方文檔橡伞。
FLAG_ACTIVITY_NEW_TASK
- 作用是為
Activity
指定“SingleTask”
啟動(dòng)模式。跟在AndroidMainfest.xml
指定效果同樣
FLAG_ACTIVITY_SINGLE_TOP
- 作用是為
Activity
指定“SingleTop”
啟動(dòng)模式晋被,跟在AndroidMainfest.xml
指定效果同樣兑徘。
FLAG_ACTIVITY_CLEAN_TOP
- 具有此標(biāo)記位的
Activity
,啟動(dòng)時(shí)會(huì)將與該Activity
在同一任務(wù)棧的其他Activity
出棧羡洛。 - 一般與
SingleTask
啟動(dòng)模式一起出現(xiàn)挂脑。 - 它會(huì)完畢
SingleTask
的作用。 - 但事實(shí)上
SingleTask
啟動(dòng)模式默認(rèn)具有此標(biāo)記位的作用
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- 具有此標(biāo)記位的
Activity
不會(huì)出如今歷史Activity
的列表中 - 使用場(chǎng)景:當(dāng)某些情況下我們不希望用戶通過(guò)歷史列表回到
Activity
時(shí)翘县,此標(biāo)記位便體現(xiàn)了它的效果。 - 它等同于在
xml
中指定Activity
的屬性.
2.7 onNewInstent()方法什么時(shí)候執(zhí)行
這個(gè)是啟動(dòng)模式中的了谴分,當(dāng)此 Activity
的實(shí)例已經(jīng)存在锈麸,并且此時(shí)的啟動(dòng)模式為 SingleTask
和 SingleInstance
,另外當(dāng)這個(gè)實(shí)例位于棧頂且啟動(dòng)模式為 SingleTop
時(shí)也會(huì)觸發(fā) onNewInstent()
牺蹄。
三忘伞、 數(shù)據(jù)
3.1 Activity 間通過(guò) Intent 傳遞數(shù)據(jù)大小限制
-
Intent
在傳遞數(shù)據(jù)時(shí)是有大小限制的,這里官方并未詳細(xì)說(shuō)明沙兰,不過(guò)通過(guò)實(shí)驗(yàn)的方法可以測(cè)出數(shù)據(jù)應(yīng)該被限制在1MB
之內(nèi)(1024KB
) - 我們采用傳遞
Bitmap
的方法氓奈,發(fā)現(xiàn)當(dāng)圖片大小超過(guò)1024
(準(zhǔn)確地說(shuō)是1020
左右)的時(shí)候,程序就會(huì)出現(xiàn)閃退鼎天、停止運(yùn)行等異常(不同的手機(jī)反應(yīng)不同) - 因此可以判斷
Intent
的傳輸容量在1MB
之內(nèi)舀奶。
3.2 內(nèi)存不足時(shí)系統(tǒng)會(huì)殺掉后臺(tái)的Activity,若需要進(jìn)行一些臨時(shí)狀態(tài)的保存斋射,在哪個(gè)方法進(jìn)行
Activity
的onSaveInstanceState()
和onRestoreInstanceState()
并不是生命周期方法育勺,它們不同于onCreate()
、onPause()
等生命周期方法罗岖,它們并不一定會(huì)被觸發(fā)涧至。onSaveInstanceState()
方法,當(dāng)應(yīng)用遇到意外情況(如:內(nèi)存不足桑包、用戶直接按Home
鍵)由系統(tǒng)銷毀一個(gè)Activity
南蓬,onSaveInstanceState()
會(huì)被調(diào)用。但是當(dāng)用戶主動(dòng)去銷毀一個(gè)
Activity
時(shí)哑了,例如在應(yīng)用中按返回鍵赘方,onSaveInstanceState()
就不會(huì)被調(diào)用。除非該
activity
不是被用戶主動(dòng)銷毀的弱左,通常onSaveInstanceState()
只適合用于保存一些臨時(shí)性的狀態(tài)蒜焊,而onPause()
適合用于數(shù)據(jù)的持久化保存。
3.3 onSaveInstanceState() 被執(zhí)行的場(chǎng)景
- 系統(tǒng)不知道你按下
HOME
后要運(yùn)行多少其他的程序科贬,自然也不知道activity A
是否會(huì)被銷毀 - 因此系統(tǒng)都會(huì)調(diào)用
onSaveInstanceState()
泳梆,讓用戶有機(jī)會(huì)保存某些非永久性的數(shù)據(jù)鳖悠。以下幾種情況的分析都遵循該原則:
- 當(dāng)用戶按下
HOME
鍵時(shí) - 長(zhǎng)按
HOME
鍵,選擇運(yùn)行其他的程序時(shí) - 鎖屏?xí)r
- 從
activity A
中啟動(dòng)一個(gè)新的activity
時(shí) - 屏幕方向切換時(shí)
3.4 兩個(gè) Activity 之間跳轉(zhuǎn)時(shí)必然會(huì)執(zhí)行的方法
一般情況下比如說(shuō)有兩個(gè) activity
, 分別叫 A
, B
,當(dāng)在 A
里面激活 B
組件的時(shí)候, A
會(huì)調(diào)用 onPause()
方法,然后 B
調(diào)用 onCreate()
, onStart()
, onResume()
优妙。
這個(gè)時(shí)候 B
覆蓋了窗體, A
會(huì)調(diào)用 onStop()
方法. 如果 B
是個(gè)透明的,或者 是對(duì)話框的樣式, 就不會(huì)調(diào)用 A
的 onStop()
方法乘综。
3.5 用 Intent 去啟動(dòng)一個(gè)Activity 之外的方法
- 使用
adb shell am
命令
-
am
啟動(dòng)一個(gè)activity
adb shell am start com.example.fuchenxuan/.MainActivity
-
am
發(fā)送一個(gè)廣播,使用action
adb shell am broadcast -a magcomm.action.TOUCH_LETTER
3.6 scheme 跳轉(zhuǎn)協(xié)議
3.6.1 定義
服務(wù)器可以定制化跳轉(zhuǎn)
app
頁(yè)面app
可以通過(guò)Scheme
跳轉(zhuǎn)到另一個(gè)app
頁(yè)面可以通過(guò)
h5
頁(yè)面跳轉(zhuǎn)app
原生頁(yè)面
3.6.2 協(xié)議格式:
qh
代表Scheme
協(xié)議名稱test
代表Scheme
作用的地址域8080
代表改路徑的端口號(hào)/goods
代表的是指定頁(yè)面(路徑)goodsId
和name
代表傳遞的兩個(gè)參數(shù)
3.6.3 Scheme使用
- 定義一個(gè)
Scheme
- 獲取
Scheme
跳轉(zhuǎn)的參數(shù)
- 調(diào)用方式
- 原生調(diào)用
- html調(diào)用
- 判斷某個(gè)Scheme是否有效
- 關(guān)于scheme跳轉(zhuǎn)協(xié)議套硼,可以查看下面的博客卡辰,站在巨人的肩膀上,才能看得更遠(yuǎn)
Android產(chǎn)品研發(fā)(十一)-->應(yīng)用內(nèi)跳轉(zhuǎn)Scheme協(xié)議
四邪意、 Context
4.1 Context , Activity , Appliction 的區(qū)別
- 相同:
Activity
和Application
都是Context
的子類九妈。 -
Context
從字面上理解就是上下文的意思, 在實(shí)際應(yīng)用中它也確實(shí)是起到了管理 上下文環(huán)境中各個(gè)參數(shù)和變量的總用, 方便我們可以簡(jiǎn)單的訪問(wèn)到各種資源。 - 不同:維護(hù)的生命周期不同雾鬼。
Context
維護(hù)的是當(dāng)前的Activity
的生命周期,Application
維護(hù)的是整個(gè)項(xiàng)目的生命周期萌朱。 - 使用
context
的時(shí)候, 小心內(nèi)存泄露, 防止內(nèi)存泄露
4.2 Context 是什么
它描述的是一個(gè)應(yīng)用程序環(huán)境的信息,即上下文。
該類是一個(gè)抽象(
abstract class
)類,Android
提供了該抽象類的具體實(shí) 現(xiàn)類(ContextIml
)策菜。通過(guò)它我們可以獲取應(yīng)用程序的資源和類, 也包括一些應(yīng)用級(jí)別操作, 例如:啟動(dòng)一個(gè)
Activity
,發(fā)送廣播,接受Intent
,信息,等晶疼。
4.2.1 附加一張 Context 繼承關(guān)系圖
[圖片上傳失敗...(image-de33df-1572405738902)]
4.3 獲取當(dāng)前屏幕 Activity 的對(duì)象
- 使用 ActivityLifecycleCallbacks
Android 如何獲取當(dāng)前Activity實(shí)例對(duì)象?
4.4 Activity 的管理機(jī)制
面試官問(wèn)這個(gè)問(wèn)題又憨,想看看大家對(duì)Activity了解是否深入:
- 什么是 ActivityRecord
- 什么是 TaskRecord
- 什么是 ActivityManagerService
4.5 什么是 Activity
- 四大組件之一翠霍,通常一個(gè)用戶交互界面對(duì)應(yīng)一個(gè)
activity
。 -
activity
是Context
的子類蠢莺,同時(shí)實(shí)現(xiàn)了window.callback
和keyevent.callback
寒匙,可以處理與窗體用戶交互的事件。 - 開(kāi)發(fā)中常用的有
FragmentActivity
躏将、ListActivity
蒋情、TabActivity
(Android 4.0
被Fragment
取代)
五、 進(jìn)程
5.1 Android 進(jìn)程優(yōu)先級(jí)
- 前臺(tái) / 可見(jiàn) / 服務(wù) / 后臺(tái) / 空
5.1.1 前臺(tái)進(jìn)程:Foreground process
- 用戶正在交互的
Activity
(onResume()
) - 當(dāng)某個(gè)
Service
綁定正在交互的Activity
- 被主動(dòng)調(diào)用為前臺(tái)
Service
(startForeground()
) - 組件正在執(zhí)行生命周期的回調(diào)(
onCreate()
耸携、onStart()
棵癣、onDestory()
) -
BroadcastReceiver
正在執(zhí)行onReceive()
5.1.2 可見(jiàn)進(jìn)程:Visible process
- 我們的
Activity
處在onPause()
(沒(méi)有進(jìn)入onStop()
) - 綁定到前臺(tái)
Activity
的Service
5.1.3 服務(wù)進(jìn)程:Service process
- 簡(jiǎn)單的
startService()
啟動(dòng)。
5.1.4 后臺(tái)進(jìn)程:Background process
- 對(duì)用戶沒(méi)有直接影響的進(jìn)程 ---
Activity
處于onStop()
的時(shí)候夺衍。 android:process=":xxx"
5.1.5 空進(jìn)程:Empty process
- 不含有任何的活動(dòng)的組件狈谊。(
Android
設(shè)計(jì)的,處于緩存的目的沟沙,為了第二次啟動(dòng)更快河劝,采取的一個(gè)權(quán)衡)
5.2 可見(jiàn)進(jìn)程
可見(jiàn)進(jìn)程指部分程序界面能夠被用戶看見(jiàn),卻不在前臺(tái)與用戶交互的進(jìn)程矛紫。例如赎瞎,我們?cè)谝粋€(gè)界面上彈出一個(gè)對(duì)話框(該對(duì)話框是一個(gè)新的
Activity
),那么在對(duì)話框后面的原界面是可見(jiàn)的颊咬,但是并沒(méi)有與用戶進(jìn)行交互务甥,那么原界面就是可見(jiàn)進(jìn)程牡辽。
- 一個(gè)進(jìn)程滿足下面任何一個(gè)條件都被認(rèn)為是可視的:
- 寄宿著一個(gè)不是前臺(tái)的活動(dòng),但是它對(duì)用戶仍可見(jiàn)(它的
onPause()
方法已經(jīng)被調(diào)用)敞临。舉例來(lái)說(shuō)态辛,這可能發(fā)生在,如果一個(gè)前臺(tái)活動(dòng)在一個(gè)對(duì)話框(其他進(jìn)程的)運(yùn)行之后仍然是可視的挺尿,比如輸入法的彈出時(shí)奏黑。 - 寄宿著一個(gè)服務(wù),該服務(wù)綁定到一個(gè)可視的活動(dòng)编矾。
- 一個(gè)可視進(jìn)程被認(rèn)為是及其重要的且不會(huì)被殺死熟史,除非為了保持前臺(tái)進(jìn)程運(yùn)行。
5.3 服務(wù)進(jìn)程
服務(wù)進(jìn)程是通過(guò)
startService()
方法啟動(dòng)的進(jìn)程窄俏,但不屬于前臺(tái)進(jìn)程和可見(jiàn)進(jìn)程蹂匹。例如,在后臺(tái)播放音樂(lè)或者在后臺(tái)下載就是服務(wù)進(jìn)程裆操。系統(tǒng)保持它們運(yùn)行怒详,除非沒(méi)有足夠內(nèi)存來(lái)保證所有的前臺(tái)進(jìn)程和可視進(jìn)程炉媒。
5.4 后臺(tái)進(jìn)程
- 后臺(tái)進(jìn)程是一個(gè)保持著一個(gè)當(dāng)前對(duì)用戶不可視的活動(dòng)(已經(jīng)調(diào)用
Activity
對(duì)象的onStop()
方法)(如果還有除了UI
線程外其他線程在運(yùn)行話踪区,不受影響)。
例如我正在使用
Home
鍵讓
- 這些進(jìn)程沒(méi)有直接影響用戶體驗(yàn)传泊,并且可以在任何時(shí)候被殺以收回內(nèi)存用于一個(gè)前臺(tái)、可視鸭巴、服務(wù)進(jìn)程眷细。
- 一般地有很多后臺(tái)進(jìn)程運(yùn)行著,因此它們保持在一個(gè)
LRU
(least recently used
鹃祖,即最近最少使用溪椎,如果您學(xué)過(guò)操作系統(tǒng)的話會(huì)覺(jué)得它很熟悉,跟內(nèi)存的頁(yè)面置換算法LRU
一樣)列表以確保最近使用最多的活動(dòng)的進(jìn)程最后被殺恬口。
5.5 空進(jìn)程
空進(jìn)程是一個(gè)沒(méi)有保持活躍的應(yīng)用程序組件的進(jìn)程校读,不包含任何活躍組件。
保持這個(gè)進(jìn)程可用的唯一原因是作為一個(gè)
cache
以提高下次啟動(dòng)組件的速度祖能。系統(tǒng)進(jìn)程殺死這些進(jìn)程歉秫,以在進(jìn)程cache
和潛在的內(nèi)核cache
之間平衡整個(gè)系統(tǒng)資源。android
進(jìn)程的回收順序從先到后分別是:空進(jìn)程养铸,后臺(tái)進(jìn)程雁芙,服務(wù)進(jìn)程轧膘,可見(jiàn)進(jìn)程,前臺(tái)進(jìn)程却特。
5.6 什么是 ANR扶供,如何避免
5.6.1 什么是ANR
-
ANR
裂明,全稱為Application Not Responding
椿浓。 - 在
Android
中,如果你的應(yīng)用程序有一段時(shí)間沒(méi)有響應(yīng)闽晦,系統(tǒng)會(huì)向用戶顯示一個(gè)對(duì)話框扳碍,這個(gè)對(duì)話框稱作應(yīng)用程序無(wú)響應(yīng)對(duì)話框。
5.6.2 用戶行為
- 用戶可以選擇讓程序繼續(xù)運(yùn)行仙蛉,也可以讓程序停止運(yùn)行笋敞。
- 他們?cè)谑褂媚愕膽?yīng)用程序時(shí),并不希望每次都要處理這個(gè)對(duì)話框荠瘪。
- 因此夯巷,在程序里對(duì)響應(yīng)性能的設(shè)計(jì)很重要,這樣哀墓,系統(tǒng)不會(huì)顯示
ANR
給用戶趁餐。
5.6.3 Android不同組件ANR超時(shí)時(shí)間不同
- 不同的組件發(fā)生
ANR
的時(shí)間不一樣,主線程(Activity
篮绰、Service
)是5
秒后雷,BroadCastReceiver
是10
秒。
5.6.4 解決方案
- 將所有耗時(shí)操作吠各,比如訪問(wèn)網(wǎng)絡(luò)臀突,
Socket
通信,查詢大量SQL
語(yǔ)句贾漏,復(fù)雜邏輯計(jì)算等都放在子線程中去候学,然后通過(guò)handler.sendMessage
、runonUITread
纵散、AsyncTask
等方式更新UI
梳码,以確保用戶界面操作的流暢度。 - 如果耗時(shí)操作需要讓用戶等待困食,那么可以在界面上顯示進(jìn)度條边翁。
5.7 android的任務(wù)棧 Task
- 一個(gè)
Task
包含的就是activity
集合,android
系統(tǒng)可以通過(guò)任務(wù)棧有序的管理activity
- 一個(gè)app當(dāng)中可能不止一個(gè)任務(wù)棧硕盹,在某些情況下符匾,一個(gè)
activity
也可以獨(dú)享一個(gè)任務(wù)棧(singleInstance
模式啟動(dòng)的activity
)
總結(jié)
- 本文基本涵蓋了
Android Activity
的所有知識(shí)點(diǎn)。對(duì)于App
啟動(dòng)瘩例、AMS
希望大家能根據(jù)文中鏈接或者Google
搜索的形式繼續(xù)展開(kāi)學(xué)習(xí)啊胶。 -
重點(diǎn)
:關(guān)于Android
的四大組件甸各,到現(xiàn)在為止我才總結(jié)完 Activity ,馬上我將繼續(xù)針對(duì)焰坪,Service
趣倾,BroadcastRecevier
等,以及事件分發(fā)某饰、滑動(dòng)沖突儒恋、新能優(yōu)化等重要模塊,進(jìn)行全面總結(jié)黔漂,歡迎大家關(guān)注 _yuanhao 的 簡(jiǎn)書(shū) 诫尽,方便及時(shí)接收更新
碼字不易,你的點(diǎn)贊是我總結(jié)的最大動(dòng)力炬守!
由于我在「稀土掘金」「簡(jiǎn)書(shū)」「
CSDN
」「博客園」等站點(diǎn)牧嫉,都有新內(nèi)容發(fā)布。所以大家可以直接關(guān)注我的GitHub
倉(cāng)庫(kù)减途,以免錯(cuò)過(guò)精彩內(nèi)容酣藻!倉(cāng)庫(kù)地址:
超級(jí)干貨!精心歸納Android
鳍置、JVM
辽剧、算法等,各位帥氣的老鐵支持一下墓捻!給個(gè) Star 抖仅!一萬(wàn)多字長(zhǎng)文坊夫,加上精美思維導(dǎo)圖砖第,記得點(diǎn)贊哦烁登,歡迎關(guān)注 _yuanhao 的 簡(jiǎn)書(shū) 倦微,我們下篇文章見(jiàn)!