從0開(kāi)始不斷溫習(xí),Android基礎(chǔ)篇-創(chuàng)新互聯(lián)

(^▽^)經(jīng)常發(fā)現(xiàn)學(xué)著學(xué)著,由于學(xué)習(xí)的東西越來(lái)越多,接觸的東西越來(lái)越多,逐漸的吧自己的最基礎(chǔ)的東西忘得差不多了(o(╥﹏╥)o我也差不多忘了很多東西了)
發(fā)現(xiàn)越優(yōu)秀的人 越注重細(xì)節(jié),基礎(chǔ)更加扎實(shí)和鞏固

公司主營(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)站回饋大家。
分享一下自己整理的面試學(xué)習(xí)路線(xiàn)

從0開(kāi)始不斷溫習(xí),Android基礎(chǔ)篇
請(qǐng)查看完整的PDF版
(更多完整項(xiàng)目下載。未完待續(xù)。源碼。圖文知識(shí)后續(xù)上傳github。)
可以點(diǎn)擊關(guān)于我聯(lián)系我獲取完整PDF
(VX:mm14525201314)

一.Activity 是什么?

Activity 實(shí)際上只是一個(gè)與用戶(hù)交互的接口而已

二.Activity 生命周期
2.1 Activity 的 4 種狀態(tài)

?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ì)話(huà)框形式的 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ì)被一并回收。

2.2 Activity 的生命周期分析

正常情況下的生命周期:
Activity 啟動(dòng)–>onCreate()–>onStart()–>onResume()
點(diǎn)擊 home 鍵回到桌面–>onPause()–>onStop()
再次回到原 Activity–>onRestart()–>onStart()–>onResume()
退出當(dāng)前 Activity 時(shí)–>onPause()–>onStop()–>onDestroy()

詳細(xì)生命周期如下:
從0開(kāi)始不斷溫習(xí),Android基礎(chǔ)篇
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)了一個(gè)新的 Activity
  • 返回上一個(gè) Activity

可以理解為當(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ì)話(huà)框彈出后 Activity 會(huì)走“9”的說(shuō)法,經(jīng)過(guò)筆者驗(yàn)證,在某個(gè) Activity 內(nèi)彈出對(duì)話(huà)框并沒(méi)有走“9”,所以網(wǎng)上大部分這樣說(shuō)法的文章要么是沒(méi)驗(yàn)證,要么直接轉(zhuǎn)載的,這個(gè)例子說(shuō)明,實(shí)驗(yàn)出真知,好了,不廢話(huà)了,那么什么情況下,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ì)話(huà)框的東東。

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)建。
從0開(kāi)始不斷溫習(xí),Android基礎(chǔ)篇

可以從圖中看出當(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ù)傳遞給 onRestoreInstanceStateonCreate 方法。所以我們可以通過(guò) onRestoreInstanceStateonCreate 方法來(lái)判斷 Actiivty 是否被重建了,如果被重建了,那么我們就可以取出之前保存的數(shù)據(jù)并恢復(fù),從時(shí)序上來(lái)看,onRestoreInstanceState 的調(diào)用時(shí)機(jī)發(fā)生在 onStart之后。

同時(shí),在 onSaveInstanceStateonRestoreInstanceState方法中,系統(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 都有 onSaveInstanceStateonRestoreInstanceState 這兩個(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ì)話(huà)框的 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ò) onSaveInstanceStateonRestoreInstanceState 來(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ù)往下看。

2.3 一些特殊情況下的生命周期分析
2.3.1 Activity 的橫豎屏切換

與橫豎屏生命周期函數(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í)候:

  1. onCreate
  2. onStart
  3. onResume
  4. 由豎屏切換到橫屏:
  5. onPause
  6. onSaveInstanceState //這里可以用來(lái)橫豎屏切換的保存數(shù)據(jù)
  7. onStop
  8. onDestroy
  9. onCreate
  10. onStart
  11. onRestoreInstanceState//這里可以用來(lái)橫豎屏切換的恢復(fù)數(shù)據(jù)
  12. onResume
  13. 橫屏切換到豎屏:
  14. onPause
  15. onSaveInstanceState
  16. onStop
  17. onDestroy
  18. onCreate
  19. onStart
  20. onRestoreInstanceState
  21. onResume

當(dāng)我們?cè)O(shè)置 Activity 的 android:configChanges 屬性為 orientation|screenSize 或者orientation|screenSize|keyboardHidden

  1. 剛剛啟動(dòng) Activity 的時(shí)候:
  2. onCreate
  3. onStart
  4. onResume
  5. 由豎屏切換到橫屏:
  6. 什么也沒(méi)有調(diào)用
  7. 橫屏切換到豎屏:
  8. 什么也沒(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 的橫豎屏切換功能的話(huà),只需要下面操作:

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)的話(huà),我們可以靈活運(yùn)用 onSaveInstanceState()方法和onRestoreInstanceState()方法。

2.3.2 什么時(shí)候 Activity 單獨(dú)走 onPause()不走 onStop()?

關(guān)于這個(gè)特殊情況,筆者在上面的生命周期圖解析的時(shí)候,貼了一個(gè)鏈接,這里主要是檢驗(yàn)?zāi)闶欠駮?huì)了這個(gè)問(wèn)題的答案,這里筆者就不貼答案了,答案全在那個(gè)鏈接里,你會(huì)了嗎?

2.3.3 什么時(shí)候?qū)е?Activity 的 onDestory()不執(zhí)行?

當(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í)行 mainactivityonDestroy 方法,activity-A(以及 activity-B)的 onDestroy方法都不會(huì)執(zhí)行;

2.4 進(jìn)程的優(yōu)先級(jí)

前臺(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í)也是最低的。

三.Android 任務(wù)棧

任務(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)模式

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è)栗子:

  • 比如目前任務(wù)棧 S1 的情況為 ABC,這個(gè)時(shí)候 Activity D 以 singleTask 模式請(qǐng)求啟動(dòng),其所需的任務(wù)棧為 S2,由于 S2 和 D 的實(shí)例均不存在,所以系統(tǒng)會(huì)先創(chuàng)建任務(wù)棧S2,然后再創(chuàng)建 D 的實(shí)例并將其投入到 S2 任務(wù)棧中。
  • 另外一種情況是,假設(shè) D 所需的任務(wù)棧為 S1,其他情況如同上面的例子所示,那么由于 S1 已經(jīng)存在,所以系統(tǒng)會(huì)直接創(chuàng)建 D 的實(shí)例并將其投入到 S1。
  • 如果 D 所需的任務(wù)棧為 S1,并且當(dāng)前任務(wù)棧 S1 的情況為 ADBC,根據(jù)棧內(nèi)復(fù)用的原則,此時(shí) D 不會(huì)重新創(chuàng)建,系統(tǒng)會(huì)把 D 切換到棧頂并調(diào)用其 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ù)棧中,換句話(huà)說(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)啟。換句話(huà)說(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ù)棧。
從0開(kāi)始不斷溫習(xí),Android基礎(chǔ)篇
如果不是請(qǐng)求的 D 而是請(qǐng)求的 C,那么情況就不一樣了,如下圖 2 所示:
從0開(kāi)始不斷溫習(xí),Android基礎(chǔ)篇
如何指定活動(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);
五.Activity組件之間的通信
六.scheme 跳轉(zhuǎn)協(xié)議

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è)面等等。

從0開(kāi)始不斷溫習(xí),Android基礎(chǔ)篇

查看完整的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í)售后在線(xiàn),公司持有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://www.muchs.cn/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)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)