目錄:
- Activity的生命周期
- Activity的任務(wù)棧
- Activity的四種啟動模式
- Activity的Flags
生命周期
下面就是老僧常談的七大生命周期了:
1. onCreate (@Nullable Bundle savedInstanceState)
一個Activity生命的開始,在這個方法中,我們通常會做一些初始化的處理,比如:初始化布局 - - setContentView;綁定UI控件 - - findViewById等。眼大的同學(xué)可能看到(眼小也能QAQ)這里需要傳入一Bundle,這個可是有大用處的,下面會具體說它,這里先不管它(①號坑)。
2.onStart
Activity正在啟動,此時的Activity已經(jīng)可見,但是并沒有出現(xiàn)在前臺,并無法與用戶進行交互。我們可以理解為,此時Activity已經(jīng)顯示出來了,但是我們并看不到。它隱身了!隱身了你能信!
3.onResume
Activity由后臺移至前臺,并且開始活動。也就是破除隱身狀態(tài),讓我們不僅可以看到它,還能操作它,點擊,滑動,任你玩。
4.onPause
此時Activity正在停止,Activity由前臺進入后臺,也就是進入隱身狀態(tài),同時不可交互。正常情況下onStop會緊接著調(diào)用,期間時間很短。如果在這個方法中進行耗時操作會影響新Activity的顯示(下面會解釋這一原因)(②號坑)。
5.onStop
此時Activity即將停止,狀態(tài)由可見轉(zhuǎn)換為不可見,也就是由隱身轉(zhuǎn)變?yōu)橄戮€。我們一般在這個方法中進行一些稍微重量型的回收工作。
6.onDestory
Activity即將進入死亡狀態(tài),馬上被回收掉,我們在這里進行重量型的回收工作。
7.onReStart
這個比較特殊,表示Activity正在重新啟動。當當前Activity由不可見(隱身)狀態(tài)進入可見(上線)狀態(tài)的時候此生命周期才會執(zhí)行。
來個完整的圖解:
這個生命周期圖比官方的生命周期圖更加清晰。
- 第一層(onCreate)-(onDestroy)表示Activity的創(chuàng)建和銷毀;
- 第二層(onStar)-(onStop)表示Activity已經(jīng)啟動,但是沒有顯示在前臺,是可見狀態(tài),但是沒有獲取焦點,也就是不可交互狀態(tài)(隱身狀態(tài));
- 第三層(onResume)-(onPause)表示Activity顯示在前臺,用戶可見并且可以交互(上線狀態(tài))。
下面開始填坑了:
①號坑: onCreate (@Nullable Bundle savedInstanceState)
可以看到這里有一個Bundle savedInstanceState,那它是干嘛的呢?
正常情況下,我們是用不到這個值的;只有在異常狀況下,我們才會用到它。
那什么是異常情況呢?
當系統(tǒng)的配置發(fā)生改變,或者系統(tǒng)在資源不足的情況下回收掉隱身的Activity。此時系統(tǒng)會調(diào)用onSaveInstanceState來保存當前Activity的狀態(tài)。這個方法是在onStop之前,但是它和onPause并沒有既定關(guān)系,它既可能在onPause之前調(diào)用,也可能在onPause之后調(diào)用。當Activity重建后,系統(tǒng)會調(diào)用onRestoreInstanceState來還原之前保存的狀態(tài)。
②號坑: Activity-A啟動Activity-B,那么這兩個Activity的生命周期是如何進行的?
如果想詳細了解這個生命周期,那需要了解Activity的啟動源碼,無奈本人水平不夠,沒法解釋,只能通過最簡單的辦法解決,新建兩個Activity,覆寫生命周期,打印log,簡單除暴,通過log顯示可以看出,只有第一個Activity的onPause執(zhí)行之后第二個Activity的onCreate才會執(zhí)行,這也就解釋了為什么不能在onPause進行耗時操作。
任務(wù)棧
關(guān)于棧結(jié)構(gòu),相信大家都不陌生,后入先出的線性表。而在Android中就是通過任務(wù)棧管理多個Activity的。
默認情況下,當一個APP啟動的時候,系統(tǒng)通常會為其創(chuàng)建一個任務(wù)棧,用于存放和管理這個APP啟動的所有Activity。當一個Activity啟動了另一個新的Activity的時候,新的Activity就會置于該任務(wù)棧的棧頂,并且處于活動狀態(tài),也就是(上線)狀態(tài)。
啟動模式
Android的Activity是四大組件之一,除了Activity的生命周期外,Activity的啟動模式也是非常重要的。為了了解Activity的啟動模式,首先我們要知道我們?yōu)槭裁匆褂脝幽J剑繂幽J酱嬖诘囊饬x是什么?
我們知道,在默認情況下,當我們多次啟動同一個Activity的時候,系統(tǒng)會創(chuàng)建多個實例,并把它們一一放入任務(wù)棧中,當我們點擊back鍵時,會發(fā)現(xiàn)這些Activity會一一回退。知道了Activity的默認啟動模式之后,我們就會發(fā)現(xiàn)一個問題:多次啟動同一個Activity,系統(tǒng)會重復(fù)創(chuàng)建多個實例,這樣很明顯是不合理的,為了解決這個問題就要用到我們說的Activity的啟動模式。目前安卓有四種啟動模式:standard、singleTop、singleTask和singleInstance,想要更改模式可以在AndroidManifest.xml中activity標簽下添加launchMode標簽。下面是各種模式的詳細介紹:
(一)standard:標準模式,這也是系統(tǒng)的默認模式。每次啟動一個Activity都會重新創(chuàng)建一個新的實例,不管實例是否已經(jīng)存在。被創(chuàng)建的實例的生命周期符合典型的Activity的生命周期。在這種模式下,誰啟動了這個Activity,那么這個Activity就運行在啟動它的那個Activity所在的棧中。比如ActivityA 啟動了ActivityB(B也是standard模式),那么B就會進入到A所在的棧中。
《Android開發(fā)藝術(shù)探索》中介紹了:如果我們用ApplicationContext去啟動standard模式的時候Activity的時候會報錯,錯誤的原因是因為standard模式的Activity默認會進入啟動它的Activity所屬的任務(wù)棧中,但是由于非Activity類型的Context(如ApplicationContext)并沒有所謂的任務(wù)棧,所有這就有問題了。解決這個問題的方法是為待啟動Activity指定FLAG_ACTIVITY_NEW_TASK標記位,這樣啟動的時候就會為它創(chuàng)建一個新的任務(wù)棧,這時候待啟動Activity實際上是一singleTask模式啟動的。
活動啟動圖:
上圖可以看出來,我們每次啟動一個A活動的時候,都會創(chuàng)建一個新的A活動放在當前棧的頂端。點擊返回鍵會回到前一個A活動,直到退出程序。你們可以寫一個小Demo自己測試親自體驗一下。
(二)singleTop:棧頂復(fù)用模式。在這種模式下,如果新Activity已經(jīng)位于任務(wù)棧的棧頂(處于完全可見狀態(tài)),那么此Activity不會被重新創(chuàng)建。但是如果新的Activity不是位于棧頂(處于不完全可見狀態(tài)),那么新Activity仍然會重新創(chuàng)建。
在singleTop(棧頂復(fù)用模式)下,如果Activity位于棧頂,我們再次啟動該方法,那么該方法會回調(diào)onNewIntent方法,而onCreate、onStart方法不會被調(diào)用。
活動啟動圖:
上圖可以看出來,如果活動B位于棧頂時,我們再次啟動活動B,則不會創(chuàng)建新的活動B,如果B不位于棧頂,則會創(chuàng)建新的活動B。
(三)singleTask:棧內(nèi)復(fù)用模式。這是一種單實例模式,在這種模式下,一個Activity在一個棧中只能有一個實例,類似單例模式。詳細講解,當一個具有singleTask模式的Activity請求啟動后,例如Activity A,系統(tǒng)首先會尋找是否存在A想要的任務(wù)棧,如果不存在,就重新創(chuàng)建一個新的任務(wù)棧,然后創(chuàng)建A的實例后把A 放到棧中。如果存在A所需要的任務(wù)棧,再看Activity A 是否在棧中有實例存在,如果有實例存在,那么系統(tǒng)就會把A調(diào)到棧頂并調(diào)用onNewIntent方法,如果實例不存在,就創(chuàng)建A的實例并把A壓入棧中。
活動啟動圖:
上圖可以看出來,活動啟動的順序是A→B→C→D→B,第一次啟動B的時候棧內(nèi)沒有實例,系統(tǒng)會創(chuàng)建新的B的實例,但第二次啟動B的時候,系統(tǒng)查詢?nèi)蝿?wù)棧,發(fā)現(xiàn)有實例,系統(tǒng)就會把活動B移到棧頂,并且把B之上的所有活動出棧。
(四)singleInstance:單實例模式。這是一種加強的singleTask模式,它除了具有singleTask模式所具有的所有特性外,還加強一點,那就是具有此種模式的Activity只能單獨的位于一個任務(wù)棧中。簡單而言,如果一個活動是singleInstance的啟動模式,那么該活動就只能單獨位于一個棧中。
活動啟動圖:
圖中看出,如果一個活動是singleInstance模式,那么活動C會單獨創(chuàng)建一個新的任務(wù)棧,而返回棧中,活動C處于的任務(wù)棧會先壓入返回棧的棧低,再把另外一個活動棧放入返回棧中。
通過Flags設(shè)置啟動模式
Activity有很多Flags,我們主要分析啟動模式相關(guān)的Flags。
- FLAG_ACTIVITY_NEW_TASK
使用一個新棧來啟動Activity,跟在xml中設(shè)置android:launchMode=“singleInstance”效果相同。 - FLAG_ACTIVITY_SINGLE_TOP
使用SingleTop模式啟動一個Activity,跟在xml中設(shè)置android:launchMode=“singleTop”效果相同 - FLAG_ACTIVITY_CLEAR_TOP
使用SingleTask模式啟動一個Activity,跟在xml中設(shè)置android:launchMode=“singleTask”效果相同 - FLAG_ACTIVITY_NO_HISTORY
使用這種模式啟動Activity,當該Activity啟動其他Activity后,該Activity就會消失,不會存留與棧中。
總結(jié):寫了三晚上終于寫完了,認真的寫一篇博客真的好難。不過認真寫博客確實能提高很多,需要認真分析問題,列出大綱,然后整理資料,書寫文章。通過這篇博客,復(fù)習(xí)了Activity的相關(guān)知識,鞏固了之前不足的地方,也發(fā)現(xiàn)了很多新的問題。以后會不斷復(fù)習(xí),不斷寫高質(zhì)量的博客。在代碼的路上奮斗下去!!!