(^▽^)經(jīng)常發(fā)現(xiàn)學(xué)著學(xué)著,由于學(xué)習(xí)的東西越來(lái)越多,接觸的東西越來(lái)越多,逐漸的吧自己的最基礎(chǔ)的東西忘得差不多了(o(╥﹏╥)o我也差不多忘了很多東西了)
公司主營(yíng)業(yè)務(wù):網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站設(shè)計(jì)、移動(dòng)網(wǎng)站開(kāi)發(fā)等業(yè)務(wù)。幫助企業(yè)客戶(hù)真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開(kāi)放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶(hù)帶來(lái)驚喜。創(chuàng)新互聯(lián)推出剛察免費(fèi)做網(wǎng)站回饋大家。
發(fā)現(xiàn)越優(yōu)秀的人 越注重細(xì)節(jié),基礎(chǔ)更加扎實(shí)和鞏固分享一下自己整理的面試學(xué)習(xí)路線
請(qǐng)查看完整的PDF版
(更多完整項(xiàng)目下載。未完待續(xù)。源碼。圖文知識(shí)后續(xù)上傳github。)
可以點(diǎn)擊關(guān)于我聯(lián)系我獲取完整PDF
(VX:mm14525201314)
Activity 實(shí)際上只是一個(gè)與用戶(hù)交互的接口而已
?Active/Paused/Stopped/Killed
Activie: 當(dāng)前 Activity 正處于運(yùn)行狀態(tài),指的是當(dāng)前 Activity 獲取了焦點(diǎn)。
Paused: 當(dāng)前 Activity 正處于暫停狀態(tài),指的是當(dāng)前 Activity 失去焦點(diǎn),此時(shí)的 Activity并沒(méi)有被銷(xiāo)毀,內(nèi)存里面的成員變量,狀態(tài)信息等仍然存在,當(dāng)然這個(gè) Activity 也仍然可見(jiàn),但是焦點(diǎn)卻不在它身上,比如被一個(gè)對(duì)話框形式的 Activity 獲取了焦點(diǎn),或者被一個(gè)透明的 Activity 獲取了焦點(diǎn),這都能導(dǎo)致當(dāng)前的 Activity 處于 paused 狀態(tài)。
Stopped: 與 paused 狀態(tài)相似,stopped 狀態(tài)的 Activity 是完全不可見(jiàn)的,但是內(nèi)存里面的成員變量,狀態(tài)信息等仍然存在,但是也沒(méi)有被銷(xiāo)毀。
Killed: 已經(jīng)被銷(xiāo)毀的 Activity 才處于 killed 狀態(tài),它的內(nèi)存里面的成員變量,狀態(tài)信息等都會(huì)被一并回收。
正常情況下的生命周期:Activity 啟動(dòng)
–>onCreate()
–>onStart()
–>onResume()
點(diǎn)擊 home 鍵回到桌面–>onPause()
–>onStop()
再次回到原 Activity
–>onRestart()
–>onStart()
–>onResume()
退出當(dāng)前 Activity
時(shí)–>onPause()
–>onStop()
–>onDestroy()
詳細(xì)生命周期如下:
1.啟動(dòng)了一個(gè) Activity,通常是 Intent 來(lái)完成。啟動(dòng)一個(gè) Activity 首先要執(zhí)行的回調(diào)函數(shù)是onCreate()
,通常在代碼中你需要在此函數(shù)中綁定布局,綁定控件,初始化數(shù)據(jù)等做一些初始化的工作。
2.即將執(zhí)行 Activity 的 onStart()
函數(shù),執(zhí)行之后 Activity 已經(jīng)可見(jiàn),但是還沒(méi)有出現(xiàn)在前臺(tái),無(wú)法與用戶(hù)進(jìn)行交互。這個(gè)時(shí)候通常 Activity 已經(jīng)在后臺(tái)準(zhǔn)備好了,但是就差執(zhí)行onResume()
函數(shù)出現(xiàn)在前臺(tái)。
3.即將執(zhí)行 Activity 的 onResume()
函數(shù),執(zhí)行之后 Activity 不止可見(jiàn)而且還會(huì)出現(xiàn)在前臺(tái),可以與用戶(hù)進(jìn)行交互啦。
4.由于 Activity 執(zhí)行了 onResume()
函數(shù),所以 Activity 出現(xiàn)在了前臺(tái)。也就是 Activity處于運(yùn)行狀態(tài)。
5.處于運(yùn)行狀態(tài)的 Activity 即將執(zhí)行 onPause()
函數(shù),什么情況下促使 Activity 執(zhí)行onPause()
方法呢?
可以理解為當(dāng)需要其他 Activity,當(dāng)前的 Activity 必須先把手頭的工作暫停下來(lái),再來(lái)把當(dāng)前的界面空間交給下一個(gè)需要界面的Activity,而 onPause()
方法可以看作是一個(gè)轉(zhuǎn)接工作的過(guò)程,因?yàn)槠聊豢臻g只有那么一個(gè),每次只允許一個(gè) Activity 出現(xiàn)在前臺(tái)進(jìn)行工作。通常情況下 onPause()函數(shù)不會(huì)被單獨(dú)執(zhí)行,執(zhí)行完 onPause()方法后會(huì)繼續(xù)執(zhí)行onStop()
方法,執(zhí)行完 onStop()
方法才真正意味著當(dāng)前的 Activity 已經(jīng)退出前臺(tái),存在于后臺(tái)。
6.Activity 即將執(zhí)行 onStop()
函數(shù),在“5”中已經(jīng)說(shuō)得很清楚了,當(dāng) Activity 要從前臺(tái)切換至后臺(tái)的時(shí)候會(huì)執(zhí)行,比如:用戶(hù)點(diǎn)擊了返回鍵,或者用戶(hù)切換至其他 Activity 等
7.當(dāng)前的 Activity 即將執(zhí)行 onDestory()
函數(shù),代表著這個(gè) Activity 即將進(jìn)入生命的終結(jié)點(diǎn),這是 Activity 生命周期中的最后一次回調(diào)生命周期,我們可以在onDestory()
函數(shù)中,進(jìn)行一些回收工作和資源的釋放工作,比如:廣播接收器的注銷(xiāo)工作等。
8.執(zhí)行完 onDestory()
方法的 Activity 接下來(lái)面對(duì)的是被 GC
回收,宣告生命終結(jié)
9.很少情況下 Activity 才走“9”,網(wǎng)上一些關(guān)于對(duì)話框彈出后 Activity 會(huì)走“9”的說(shuō)法,經(jīng)過(guò)筆者驗(yàn)證,在某個(gè) Activity 內(nèi)彈出對(duì)話框并沒(méi)有走“9”,所以網(wǎng)上大部分這樣說(shuō)法的文章要么是沒(méi)驗(yàn)證,要么直接轉(zhuǎn)載的,這個(gè)例子說(shuō)明,實(shí)驗(yàn)出真知,好了,不廢話了,那么什么情況下,Activity 會(huì)走“9”呢?
10.當(dāng)用戶(hù)在其他的 Activity 或者桌面回切到這個(gè) Activity 時(shí),這個(gè) Activity 就會(huì)先去執(zhí)行onRestart()
函數(shù),Restart 有“重新開(kāi)始”的意思,然后接下來(lái)執(zhí)行 onStart()
函數(shù),接著執(zhí)行 onResume()
函數(shù)進(jìn)入到運(yùn)行狀態(tài)。
11.在“10”中講的很清楚了。
12.高優(yōu)先級(jí)的應(yīng)用急需要內(nèi)存,此時(shí)處于低優(yōu)先級(jí)的此應(yīng)用就會(huì)被 kill 掉。
13.用戶(hù)返回原 Activity。
下面來(lái)著重說(shuō)明一下 Activity 每個(gè)生命周期函數(shù):onCreate()
:
表示 Activity 正在被創(chuàng)建,這是 Activity 生命周期的第一個(gè)方法。通常我們程序員要在此函數(shù)中做初始化的工作,比如:綁定布局,控件,初始化數(shù)據(jù)等。
onStart()
:
表示 Activity 正在被啟動(dòng),這時(shí)候的 Activity 已經(jīng)被創(chuàng)建好了,完全過(guò)了準(zhǔn)備階段,但是沒(méi)有出現(xiàn)在前臺(tái),需要執(zhí)行 onResume()
函數(shù)才可以進(jìn)入到前臺(tái)與用戶(hù)進(jìn)行交互。
onResume()
:
表示 Activitiy 已經(jīng)可見(jiàn)了,并且 Activity 處于運(yùn)行狀態(tài),也就是 Activity 不止出現(xiàn)在了前臺(tái),而且還可以讓用戶(hù)點(diǎn)擊,滑動(dòng)等等操作與它進(jìn)行交互。
onPause()
:
表示 Activity 正在暫停,大多數(shù)情況下,Activity 執(zhí)行完 onPause()
函數(shù)后會(huì)繼續(xù)執(zhí)行onStop()
函數(shù),造成這種函數(shù)調(diào)用的原因是當(dāng)前的 Activity 啟動(dòng)了另外一個(gè) Activity 或者回切到上一個(gè) Activity。還有一種情況就是 onPause()
函數(shù)被單獨(dú)執(zhí)行了,并沒(méi)有附帶執(zhí)行 onStop()
方法,造成這種函數(shù)調(diào)用的原因很簡(jiǎn)單,就是當(dāng)前 Activity 里啟動(dòng)了類(lèi)似于對(duì)話框的東東。
onStop()
:
表示 Activity 即將停止,我們程序員應(yīng)該在此函數(shù)中做一些不那么耗時(shí)的輕量級(jí)回收操作。
onRestart()
:
表示 Activity 正在重新啟動(dòng)。一般情況下,一個(gè)存在于后臺(tái)不可見(jiàn)的 Activity 變?yōu)榭梢?jiàn)狀態(tài),都會(huì)去執(zhí)行 onRestart()
函數(shù),然后會(huì)繼續(xù)執(zhí)行onStart()
函數(shù),onResume()
函數(shù)出現(xiàn)在前臺(tái)并且處于運(yùn)行狀態(tài)。
onDestory()
:
表示 Activity 要被銷(xiāo)毀了。這是 Activity 生命中的最后一個(gè)階段,我們可以在onDestory()
函數(shù)中做一些回收工作和資源釋放等,比如:廣播接收器的注銷(xiāo)等。
異常情況下的生命周期:
什么是異常情況呢?
情況 1: 資源相關(guān)的系統(tǒng)配置發(fā)生改變導(dǎo)致 Activity 被殺死并重新創(chuàng)建。
可以從圖中看出當(dāng) Activity 發(fā)生意外的情況的時(shí)候,這里的意外指的就是系統(tǒng)配置發(fā)生改變,Activity 會(huì)被銷(xiāo)毀,其onPause
,OnStop
,onDestory
函數(shù)均會(huì)被調(diào)用,同時(shí)由于Actiivty
是在異常情況下終止的,系統(tǒng)會(huì)調(diào)用onSaveInstanceState
來(lái)保存當(dāng)前 Activity狀態(tài)。調(diào)用 onSaveInstanceState
的時(shí)機(jī)總會(huì)發(fā)生在 onStop
之前,至于會(huì)不會(huì)調(diào)用時(shí)機(jī)發(fā)生在 onPause
方法之前,那就說(shuō)不定了,這個(gè)沒(méi)有固定的順序可言,正常情況下一般onSaveInstanceState
不會(huì)被調(diào)用。當(dāng) Activity 被重新創(chuàng)建后,系統(tǒng)會(huì)調(diào)用onRestoreInstanceState
,并且把 Actiivty
銷(xiāo)毀時(shí) onSaveInstanceState
方法所保存的Bundle 對(duì)象作為參數(shù)傳遞給 onRestoreInstanceState
和 onCreate
方法。所以我們可以通過(guò) onRestoreInstanceState
和 onCreate
方法來(lái)判斷 Actiivty
是否被重建了,如果被重建了,那么我們就可以取出之前保存的數(shù)據(jù)并恢復(fù),從時(shí)序上來(lái)看,onRestoreInstanceState
的調(diào)用時(shí)機(jī)發(fā)生在 onStart
之后。
同時(shí),在 onSaveInstanceState
和 onRestoreInstanceState
方法中,系統(tǒng)自動(dòng)為我們做了一定的恢復(fù)工作。當(dāng) Activity 在異常情況下需要重新創(chuàng)建時(shí),系統(tǒng)會(huì)默認(rèn)為我們保存當(dāng)前 Activity 的視圖結(jié)構(gòu)。當(dāng) Activity 在異常情況下需要重新創(chuàng)建時(shí),系統(tǒng)會(huì)默認(rèn)為我們保存當(dāng)前 Activity 的視圖結(jié)構(gòu),并且在 Activity 重啟后為我們恢復(fù)這些數(shù)據(jù),比如:文本框中用戶(hù)輸入的數(shù)據(jù),ListView
滾動(dòng)的位置等,這些 View 相關(guān)的狀態(tài)系統(tǒng)都能夠默認(rèn)為我們恢復(fù)。具體針對(duì)某一個(gè)特定的 View 系統(tǒng) 能為我們恢復(fù)哪些數(shù)據(jù),我們可以查看 View 的源碼。和 Activity 一樣,每個(gè) View 都有 onSaveInstanceState
和onRestoreInstanceState
這兩個(gè)方法,看一下它們的具體實(shí)現(xiàn),就能知道系統(tǒng)能夠自動(dòng)為每個(gè) View 恢復(fù)哪些數(shù)據(jù)
關(guān)于保存和恢復(fù) View 層次結(jié)構(gòu),系統(tǒng)的工作流程是這樣的:
首先 Activity 被意外終止時(shí),Activity 會(huì)調(diào)用 onSaveInstanceState
去保存數(shù)據(jù),然后Activity 會(huì)委托 Window 去保存數(shù)據(jù),接著 Window 在委托它上面的頂級(jí)容器去保存數(shù)據(jù)。頂級(jí)容器是一個(gè) ViewGroup
,一般來(lái)說(shuō)它很可能是 DecorView
。最后頂層容器再去一一通知它的子元素來(lái)保存數(shù)據(jù),這樣整個(gè)數(shù)據(jù)保存過(guò)程就完成了??梢园l(fā)現(xiàn),這是一個(gè)典型的委托思想,上層委托下層,父容器去委托子元素去處理一件事情,這種思想在Android 中有很多應(yīng)用,比如:View 的繪制過(guò)程,事件分發(fā)等都是采用類(lèi)似的思想。至于數(shù)據(jù)恢復(fù)過(guò)程也是類(lèi)似的,這樣就不再重復(fù)介紹了。
情況 2: 資源內(nèi)存不足導(dǎo)致低優(yōu)先級(jí)的 Activity 被殺死。
首先,Activity 有優(yōu)先級(jí)?你肯定懷疑,代碼中都沒(méi)設(shè)置過(guò)??!優(yōu)先級(jí)從何而來(lái),其實(shí)這里的 Activity 的優(yōu)先級(jí)是指一個(gè) Activity 對(duì)于用戶(hù)的重要程度,比如:正在與用戶(hù)進(jìn)行交互的 Activity 那肯定是最重要的。我們可以按照重要程度將 Activity 分為以下等級(jí):
優(yōu)先級(jí)高: 與用戶(hù)正在進(jìn)行交互的 Activity,即前臺(tái) Activity。
優(yōu)先級(jí)中等: 可見(jiàn)但非前臺(tái)的 Activity,比如:一個(gè)彈出對(duì)話框的 Activity,可見(jiàn)但是非前臺(tái)運(yùn)行。
優(yōu)先級(jí)最低: 完全存在與后臺(tái)的 Activity,比如:執(zhí)行了onStop
。
當(dāng)內(nèi)存嚴(yán)重不足時(shí),系統(tǒng)就會(huì)按照上述優(yōu)先級(jí)去 kill 掉目前 Activity 所在的進(jìn)程,并在后續(xù)通過(guò) onSaveInstanceState
和 onRestoreInstanceState
來(lái)存儲(chǔ)和恢復(fù)數(shù)據(jù)。如果一個(gè)進(jìn)程中沒(méi)有四大組件的執(zhí)行,那么這個(gè)進(jìn)程將很快被系統(tǒng)殺死,因此,一些后臺(tái)工作不適合脫離四大組件獨(dú)立運(yùn)行在后臺(tái)中,這樣進(jìn)程更容易被殺死。比較好的方法就是將后臺(tái)工作放入 Service 中從而保證進(jìn)程有一定的優(yōu)先級(jí),這樣就不會(huì)輕易地被系統(tǒng)殺死
總結(jié):
上面分析了系統(tǒng)的數(shù)據(jù)存儲(chǔ)和恢復(fù)機(jī)制,我們知道,當(dāng)系統(tǒng)配置發(fā)生改變之后,Activity會(huì)被重新創(chuàng)建,那么有沒(méi)有辦法不重新創(chuàng)建呢?答案是有的,接下來(lái)我們就來(lái)分析這個(gè)問(wèn)題。系統(tǒng)配置中有很多內(nèi)容,如果某項(xiàng)內(nèi)容發(fā)生了該變后,我們不想系統(tǒng)重新創(chuàng)建Activity 可以給 Activity 指定 configChanges
屬性。比如我們不想讓 Actiivty
在屏幕旋轉(zhuǎn)的時(shí)候重新創(chuàng)建,就可以給configChanges
屬性添加一些值,請(qǐng)繼續(xù)往下看。
與橫豎屏生命周期函數(shù)有關(guān)調(diào)用的屬性是"android:configChanges"
,關(guān)于它的屬性值設(shè)置影響如下:
orientation
:消除橫豎屏的影響keyboardHidden
:消除鍵盤(pán)的影響screenSize
:消除屏幕大小的影響當(dāng)我們?cè)O(shè)置 Activity 的 android:configChanges
屬性為 orientation
或者orientation
|keyboardHidden
或者不設(shè)置這個(gè)屬性的時(shí)候,它的生命周期會(huì)走如下流程:
1.剛剛啟動(dòng) Activity 的時(shí)候:
- onCreate
- onStart
- onResume
- 由豎屏切換到橫屏:
- onPause
- onSaveInstanceState //這里可以用來(lái)橫豎屏切換的保存數(shù)據(jù)
- onStop
- onDestroy
- onCreate
- onStart
- onRestoreInstanceState//這里可以用來(lái)橫豎屏切換的恢復(fù)數(shù)據(jù)
- onResume
- 橫屏切換到豎屏:
- onPause
- onSaveInstanceState
- onStop
- onDestroy
- onCreate
- onStart
- onRestoreInstanceState
- onResume
當(dāng)我們?cè)O(shè)置 Activity 的 android:configChanges
屬性為 orientation
|screenSize
或者orientation
|screenSize
|keyboardHidden
- 剛剛啟動(dòng) Activity 的時(shí)候:
- onCreate
- onStart
- onResume
- 由豎屏切換到橫屏:
- 什么也沒(méi)有調(diào)用
- 橫屏切換到豎屏:
- 什么也沒(méi)有調(diào)用
而且需要注意一點(diǎn)的是設(shè)置了 orientation
|screenSize
屬性之后,在進(jìn)行橫豎屏切換的時(shí)候調(diào)用的方法是 onConfigurationChanged()
,而不會(huì)回調(diào) Activity 的各個(gè)生命周期函數(shù);
當(dāng)然在顯示中我們可以屏蔽掉橫豎屏的切換操作,這樣就不會(huì)出現(xiàn)切換的過(guò)程中 Activity生命周期重新加載的情況了,具體做法是,在 Activity 中加入如下語(yǔ)句:
android:screenOrientation="portrait"
始終以豎屏顯示android:screenOrientation="landscape"
始終以橫屏顯示
如果不想設(shè)置整個(gè)軟件屏蔽橫豎屏切換,只想設(shè)置屏蔽某個(gè) Activity 的橫豎屏切換功能的話,只需要下面操作:
Activity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
;以豎屏顯示Activity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
;以橫屏顯示
最后提一點(diǎn),當(dāng)你橫豎屏切換的時(shí)候,如果走了銷(xiāo)毀 Activity 的流程,那么需要保存當(dāng)前和恢復(fù)當(dāng)前 Activity 的狀態(tài)的話,我們可以靈活運(yùn)用 onSaveInstanceState()
方法和onRestoreInstanceState()
方法。
關(guān)于這個(gè)特殊情況,筆者在上面的生命周期圖解析的時(shí)候,貼了一個(gè)鏈接,這里主要是檢驗(yàn)?zāi)闶欠駮?huì)了這個(gè)問(wèn)題的答案,這里筆者就不貼答案了,答案全在那個(gè)鏈接里,你會(huì)了嗎?
當(dāng)用戶(hù)后臺(tái)強(qiáng)殺應(yīng)用程序時(shí),當(dāng)前返回棧僅有一個(gè) activity 實(shí)例時(shí),這時(shí)候,強(qiáng)殺,是會(huì)執(zhí)行 onDestroy
方法的;當(dāng)返回棧里面存在多個(gè) Activity 實(shí)例時(shí),棧里面的第一個(gè)沒(méi)有銷(xiāo)毀的 activity 執(zhí)行會(huì) ondestroy
方法,其他的不會(huì)執(zhí)行;比如說(shuō):從 mainactivity
跳轉(zhuǎn)到activity-A(或者繼續(xù)從 activity-A 再跳轉(zhuǎn)到 activity-B),這時(shí)候,從后臺(tái)強(qiáng)殺,只會(huì)執(zhí)行 mainactivity
的 onDestroy
方法,activity-A(以及 activity-B)的 onDestroy
方法都不會(huì)執(zhí)行;
前臺(tái)>可見(jiàn)>服務(wù)>后臺(tái)>空
前臺(tái): 與當(dāng)前用戶(hù)正在交互的 Activity 所在的進(jìn)程。
可見(jiàn): Activity 可見(jiàn)但是沒(méi)有在前臺(tái)所在的進(jìn)程。
服務(wù): Activity 在后臺(tái)開(kāi)啟了 Service 服務(wù)所在的進(jìn)程。
后臺(tái): Activity 完全處于后臺(tái)所在的進(jìn)程。
空: 沒(méi)有任何 Activity 存在的進(jìn)程,優(yōu)先級(jí)也是最低的。
任務(wù)棧與 Activity 的啟動(dòng)模式密不可分,它是用來(lái)存儲(chǔ) Activity 實(shí)例的一種數(shù)據(jù)結(jié)構(gòu),Activity 的跳轉(zhuǎn)以及回跳都與這個(gè)任務(wù)棧有關(guān)。詳情請(qǐng)看下面的 Activity 的啟動(dòng)模式。
Activity 的啟動(dòng)模式,你在初學(xué)期間一定很熟悉了吧!不管你是否熟悉還是不熟悉,跟隨筆者的思路把 Activity 的啟動(dòng)模式整理一遍:
問(wèn)題 1: Activity 為什么需要啟動(dòng)模式?
問(wèn)題 2: Activity 的啟動(dòng)模式有哪些?特性如何
問(wèn)題 3: 如何給 Activity 選擇合適的啟動(dòng)模式
問(wèn)題 1:Activity 為什么需要啟動(dòng)模式?
我們都知道啟動(dòng)一個(gè) Activity 后,這個(gè) Activity 實(shí)例就會(huì)被放入任務(wù)棧中,當(dāng)點(diǎn)擊返回鍵的時(shí)候,位于任務(wù)棧頂層的 Activity 就會(huì)被清理出去,當(dāng)任務(wù)棧中不存在任何 Activity 實(shí)例后,系統(tǒng)就回去回收這個(gè)任務(wù)棧,也就是程序退出了。這只是對(duì)任務(wù)棧的基本認(rèn)識(shí),深入學(xué)習(xí),筆者會(huì)在之后文章中提到。那么問(wèn)題來(lái)了,既然每次啟動(dòng)一個(gè) Activity 就會(huì)把對(duì)應(yīng)的要啟動(dòng)的 Activity 的實(shí)例放入任務(wù)棧中,假如這個(gè) Activity 會(huì)被頻繁啟動(dòng),那豈不是會(huì)生成很多這個(gè) Activity 的實(shí)例嗎?對(duì)內(nèi)存而言這可不是什么好事,明明可以一個(gè)Activity 實(shí)例就可以應(yīng)付所有的啟動(dòng)需求,為什么要頻繁生成新的 Activity 實(shí)例呢?杜絕這種內(nèi)存的浪費(fèi)行為,所以 Activity 的啟動(dòng)模式就被創(chuàng)造出來(lái)去解決上面所描述的問(wèn)題。
問(wèn)題 2:Activity 的啟動(dòng)模式有哪些?特性如何
Activity 的啟動(dòng)模式有 4 種,分別是:standard,singleTop,singleTask 和singleInstance。
下面一一作介紹:
1.系統(tǒng)默認(rèn)的啟動(dòng)模式:Standard
標(biāo)準(zhǔn)模式,這也是系統(tǒng)的默認(rèn)模式。每次啟動(dòng)一個(gè) Activity 都會(huì)重新創(chuàng)建一個(gè)新的實(shí)例,不管這個(gè)實(shí)例是否存在。被創(chuàng)建的實(shí)例的生命周期符合典型情況下的 Activity 的生命周期。在這種模式下,誰(shuí)啟動(dòng)了這個(gè) Activity,那么這個(gè) Activity 就運(yùn)行在啟動(dòng)它的那個(gè)Activity 的任務(wù)棧中。比如 Activity A 啟動(dòng)了 Activity B(B 是標(biāo)準(zhǔn)模式),那么 B 就會(huì)進(jìn)入到 A 所在的任務(wù)棧中。有個(gè)注意的地方就是當(dāng)我們用 ApplicationContext
去啟動(dòng)standard 模式的 Activity 就會(huì)報(bào)錯(cuò),這是因?yàn)?standard 模式的 Actiivty
默認(rèn)會(huì)進(jìn)入啟動(dòng)它的 Activity 所屬的任務(wù)棧中,但是由于非 Activity 類(lèi)型的 Context(ApplicationContext)
并沒(méi)有所謂的任務(wù)棧,所以這就會(huì)出現(xiàn)錯(cuò)誤。解決這個(gè)問(wèn)題的方法就是為待啟動(dòng)的 Activity 指定 FLAG_ACTIVITY_NEW_TASK 標(biāo)記位,這樣啟動(dòng)的時(shí)候就會(huì)為它創(chuàng)建一個(gè)新的任務(wù)棧,這個(gè)時(shí)候啟動(dòng) Activity 實(shí)際上以singleTask 模式啟動(dòng)的,讀者可以自己仔細(xì)體會(huì)。
2.棧頂復(fù)用模式:SingleTop
在這種模式下,如果新的 Activity 已經(jīng)位于任務(wù)棧的棧頂,那么此 Activity 不會(huì)被重新創(chuàng)建,同時(shí)它的 onNewIntent
方法被回調(diào),通過(guò)此方法的參數(shù)我們可以取出當(dāng)前請(qǐng)求的信息。需要注意的是,這個(gè) Activity 的 onCreate
,onStart
不會(huì)被系統(tǒng)調(diào)用,因?yàn)樗](méi)有發(fā)生改變。如果新的 Activity 已經(jīng)存在但不是位于棧頂,那么新的 Activity 仍然會(huì)重新重建。舉個(gè)例子,假設(shè)目前棧內(nèi)的情況為 ABCD,其中 ABCD 為四個(gè) Activity,A 位于棧低,D 位于棧頂,這個(gè)時(shí)候假設(shè)要再次啟動(dòng) D,如果 D 的啟動(dòng)模式為 singleTop
,那么棧內(nèi)的情況依然為 ABCD;如果 D 的啟動(dòng)模式為 standard,那么由于 D 被重新創(chuàng)建,導(dǎo)致棧內(nèi)的情況為 ABCDD。
3.棧內(nèi)復(fù)用模式:SingTask
這是一種單例實(shí)例模式,在這種模式下,只要 Activity 在一個(gè)棧中存在,那么多次啟動(dòng)此Activity 都不會(huì)重新創(chuàng)建實(shí)例,和 singleTop
一樣,系統(tǒng)也會(huì)回調(diào)其 onNewIntent
。具體一點(diǎn),當(dāng)一個(gè)具有 singleTask
模式的 Activity 請(qǐng)求啟動(dòng)后,比如 Activity A,系統(tǒng)首先尋找任務(wù)棧中是否已存在 Activity A 的實(shí)例,如果已經(jīng)存在,那么系統(tǒng)就會(huì)把 A 調(diào)到棧頂并調(diào)用它的 onNewIntent
方法,如果 Activity A 實(shí)例不存在,就創(chuàng)建 A 的實(shí)例并把 A 壓入棧中。舉幾個(gè)栗子:
onNewIntent
方法,同時(shí)由于 singleTask
默認(rèn)具有clearTop
的效果,會(huì)導(dǎo)致棧內(nèi)所有在 D 上面的 Activity全部出棧,于是最終 S1 中的情況為 AD。通過(guò)以上 3 個(gè)例子,你應(yīng)該能比較清晰地理解 singleTask 的含義了。
4.單實(shí)例模式:SingleInstance
這是一種加強(qiáng)的 singleTask
模式,它除了具有 singleTask
模式所有的特性外,還加強(qiáng)了一點(diǎn),那就是具有此種模式的 Activity 只能單獨(dú)位于一個(gè)任務(wù)棧中,換句話說(shuō),比如Activity A 是 singleInstance
模式,當(dāng) A 啟動(dòng)后,系統(tǒng)會(huì)為它創(chuàng)建一個(gè)新的任務(wù)棧,然后A 獨(dú)自在這個(gè)新的任務(wù)棧中,由于棧內(nèi)復(fù)用的特性,后續(xù)的請(qǐng)求均不會(huì)創(chuàng)建新的 Activity,除非這個(gè)獨(dú)特的任務(wù)棧被系統(tǒng)銷(xiāo)毀了。
對(duì)于 SingleInstance
,面試時(shí)你有說(shuō)明它的以下幾個(gè)特點(diǎn):
(1) 以 singleInstance
模式啟動(dòng)的 Activity 具有全局唯一性,即整個(gè)系統(tǒng)中只會(huì)存在一個(gè)這樣的實(shí)例。
(2) 以 singleInstance
模式啟動(dòng)的 Activity 在整個(gè)系統(tǒng)中是單例的,如果在啟動(dòng)這樣的Activiyt
時(shí),已經(jīng)存在了一個(gè)實(shí)例,那么會(huì)把它所在的任務(wù)調(diào)度到前臺(tái),重用這個(gè)實(shí)例。
(3) 以singleInstance
模式啟動(dòng)的 Activity 具有獨(dú)占性,即它會(huì)獨(dú)自占用一個(gè)任務(wù),被他開(kāi)啟的任何 activity 都會(huì)運(yùn)行在其他任務(wù)中。
(4) 被 singleInstance
模式的 Activity 開(kāi)啟的其他 activity,能夠在新的任務(wù)中啟動(dòng),但不一定開(kāi)啟新的任務(wù),也可能在已有的一個(gè)任務(wù)中開(kāi)啟。換句話說(shuō),其實(shí) SingleInstance
就是我們剛才分析的 SingleTask
中,分享 Activity 為棧底元素的情況。
總結(jié)
上面介紹了 4 種啟動(dòng)模式,這里需要指出一種情況,我們假設(shè)目前有 2 個(gè)任務(wù)棧,前臺(tái)任務(wù)棧的情況為 AB,而后臺(tái)任務(wù)棧的情況為 CD,這里假設(shè) CD 的啟動(dòng)模式均為singleTask
?,F(xiàn)在請(qǐng)求啟動(dòng) D,那么整個(gè)后臺(tái)任務(wù)棧都會(huì)被切換到前臺(tái),這個(gè)時(shí)候整個(gè)后退列表變成了 ABCD。當(dāng)用戶(hù)按 back 鍵的時(shí)候,列表中的 Activity 會(huì)一一出棧,如下圖 1所示:
注意:
前臺(tái)任務(wù)棧: 就是指和用戶(hù)正在交互的應(yīng)用程序所在的任務(wù)棧。
后臺(tái)任務(wù)棧: 就是指處于后臺(tái)的應(yīng)用程序所在的任務(wù)棧。
如果不是請(qǐng)求的 D 而是請(qǐng)求的 C,那么情況就不一樣了,如下圖 2 所示:
如何指定活動(dòng)的啟動(dòng)模式呢?在 AndroidManifest.xml 文件當(dāng)注冊(cè)活動(dòng)的代碼中去指定
比如: 我要把 MainActivity
活動(dòng)的啟動(dòng)模式指定為 singleInstance
模式
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singlelnstance">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
也可以在代碼中指定:
Intent pack = new Inten(MCPersonalCenterActivity.this,MCGiftsCenterActivity.class);
pack.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(pack);
Android 中的 scheme 是一種頁(yè)面內(nèi)跳轉(zhuǎn)協(xié)議,通過(guò)自定義 scheme 協(xié)議,可以非常方便的跳轉(zhuǎn)到 app 中的各個(gè)頁(yè)面,通過(guò) scheme 協(xié)議,服務(wù)器可以定制化告訴 app 跳轉(zhuǎn)到哪個(gè)頁(yè)面,可以通過(guò)通知欄消息定制化跳轉(zhuǎn)頁(yè)面,可以通過(guò) H5 頁(yè)面跳轉(zhuǎn)到相應(yīng)頁(yè)面等等。
查看完整的PDF版
(更多完整項(xiàng)目下載。未完待續(xù)。源碼。圖文知識(shí)后續(xù)上傳github。)
可以點(diǎn)擊關(guān)于我聯(lián)系我獲取完整PDF
(VX:mm14525201314)
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿(mǎn)足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。
文章名稱(chēng):從0開(kāi)始不斷溫習(xí),Android基礎(chǔ)篇-創(chuàng)新互聯(lián)
網(wǎng)頁(yè)路徑:http://jinyejixie.com/article10/diegdo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制開(kāi)發(fā)、網(wǎng)站收錄、網(wǎng)站設(shè)計(jì)、網(wǎng)站維護(hù)、Google、搜索引擎優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容