Activity的基本理解
一.生命周期
?上面是經典的Activity的生命周期圖 標準啟動模式下的生命周期十一上圖中的7個:
onCreate onDestroy onStart onRestart onStop onResume onPause生命周期都是成對對應的
activity最基本的生命周期:
onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy1.各個生命周期含義及應用場景
(1)onCreate:create表示創建,這是Activity生命周期的第一個方法,也是我們在android開發中接觸的最多的生命周期方法。它本身的作用是進行Activity的一些初始化工作,比如使用setContentView加載布局,對一些控件和變量進行初始化等。但也有很多人將很多與初始化無關的代碼放在這,其實這是不規范的。此時Activity還在后臺,不可見。所以動畫不應該在這里初始化,因為看不到……
(2)onStart:start表示啟動,這是Activity生命周期的第二個方法。此時Activity已經可見了,但是還沒出現在前臺,我們還看不到,無法與Activity交互。其實將Activity的初始化工作放在這也沒有什么問題,放在onCreate中是由于官方推薦的以及我們開發的習慣。
(3)onResume:resume表示繼續、重新開始,這名字和它的職責也相同。此時Activity經過前兩個階段的初始化已經蓄勢待發。Activity在這個階段已經出現在前臺并且可見了。這個階段可以打開獨占設備
(4)onPause:pause表示暫停,當Activity要跳到另一個Activity或應用正常退出時都會執行這個方法。此時Activity在前臺并可見,我們可以進行一些輕量級的存儲數據和去初始化的工作,不能太耗時,因為在跳轉Activity時只有當一個Activity執行完了onPause方法后另一個Activity才會啟動,而且android中指定如果onPause在500ms即0.5秒內沒有執行完畢的話就會強制關閉Activity。從生命周期圖中發現可以在這快速重啟,但這種情況其實很罕見,比如用戶切到下一個Activity的途中按back鍵快速得切回來。
(5)onStop:stop表示停止,此時Activity已經不可見了,但是Activity對象還在內存中,沒有被銷毀。這個階段的主要工作也是做一些資源的回收工作。
(6)onDestroy:destroy表示毀滅,這個階段Activity被銷毀,不可見,我們可以將還沒釋放的資源釋放,以及進行一些回收工作。
(7)onRestart:restart表示重新開始,Activity在這時可見,當用戶按Home鍵切換到桌面后又切回來或者從后一個Activity切回前一個Activity就會觸發這個方法。這里一般不做什么操作。
一些常見的場景:
當用戶點擊A中按鈕來到B時,假設B全部遮擋住了A,將依次執行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop。此時如果點擊Back鍵,將依次執行B:onPause -> A:onRestart -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。至此,Activity棧中只有A。在Android中,有兩個按鍵在影響Activity生命周期這塊需要格外區分下,即Back鍵和Home鍵。我們先直接看下實驗結果:此時如果按下Back鍵,系統返回到桌面,并依次執行A:onPause -> A:onStop -> A:onDestroy。此時如果按下Home鍵(非長按),系統返回到桌面,并依次執行A:onPause -> A:onStop。由此可見,Back鍵和Home鍵主要區別在于是否會執行onDestroy。此時如果長按Home鍵,不同手機可能彈出不同內容,Activity生命周期未發生變化(由小米2s測的,不知道其他手機是否會對Activity生命周期有影響)。2.onCreate和onStart之間有什么區別?
(1)可見與不可見的區別。前者不可見,后者可見。
(2)執行次數的區別。onCreate方法只在Activity創建時執行一次,而onStart方法在Activity的切換 以及按Home鍵返回桌面再切回應用的過程中被多次調用。因此Bundle數據的恢復在onStart中進行比onCreate中執行更合適。
(3)onCreate能做的事onStart其實都能做,但是onstart能做的事onCreate卻未必適合做。 如前文所說的,setContentView和資源初始化在兩者都能做,然而想動畫的初始化在onStart中做比較好。
3.onStart方法和onResume方法有什么區別?
(1)是否在前臺。onStart方法中Activity可見但不在前臺,不可交互,而在onResume中在前臺。
(2)職責不同,onStart方法中主要還是進行初始化工作,而onResume方法,根據官方的建議,可以做開啟動畫和獨占設備的操作。
4.onPause方法和onStop方法有什么區別?
(1)是否可見。onPause時Activity可見,onStop時Activity不可見,但Activity對象還在內存中。
(2)在系統內存不足的時候可能不會執行onStop方法,因此程序狀態的保存、 獨占設備和動畫的關閉、以及一些數據的保存最好在onPause中進行,但要注意不能太耗時。
5.onStop方法和onDestroy方法有什么區別?
onStop階段Activity還沒有被銷毀,對象還在內存中,此時可以通過切換Activity再次回到該Activity,而onDestroy階段Acivity被銷毀
6.為什么切換Activity時各方法的執行次序是(A)onPause→(B)onCreate→(B)onStart→(B)onResume→(A)onStop而不是(A)onPause→(A)onStop→(B)onCreate→(B)onStart→(B)onResume
(1)一個Activity或多或少會占有系統資源,而在官方的建議中,onPause方 法將會釋放掉很多系統資源,為切換Activity提供流暢性的保障,而不需要再等多兩個階段,這樣做切換更快。
(2)按照生命周期圖的表示,如果用戶在切換Activity的過程中再次切回原Activity,是在onPause方法后直接調用onResume方法的,這樣比onPause→onStop→onRestart→onStart→onResume要快得多。
7.與生命周期密切相關的onSaveInstanceState方法和onRestoreInstanceState方法在什么時候執行?
通過閱讀源碼會發現,當targetSdkVersion小于3時onSaveInstanceState是在onPause方法中調用的,而大于3時是在onStop方法中調用的。 而onRestoreInstanceState是在onStart之后、onResume之前調用的。
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它們不同于 onCreate()、onPause()等生命周期方法,它們并不一定會被觸發。 當應用遇到意外情況(如:內存不足、用戶直接按Home鍵)由系統銷毀一個Activity時,onSaveInstanceState() 會被調用。但是當用戶主動去銷毀一個Activity時,例如在應用中按返回鍵, onSaveInstanceState()就不會被調用。因為在這種情況下,用戶的行為決定 了不需要保存Activity的狀態。 通常onSaveInstanceState()只適合用于保存一些臨時性的狀態,而onPause()適合用于數據的持久化保存。
8.onNewIntent()
第一種情況:activity launchMode為singleTask或者singleInstance
1、activitya start activityb
2、activityb start activitya
在第二步被執行后,activitya就會順序執行 onNewIntent onRestart onStart onResume
第二種情況:activity launchMode為singleTop singleTask singleInstance
1、start activitya
2、activitya start activitya
在第二步被執行后,activitya就會順序執行onPause onNewIntent onResume
第一種情況其實是真正的activity被restart,第二種情況是activity位于棧頂時被再次start就會進入onNewIntent
其實理解的簡單一點,無論什么模式,只有activity是同一個實例的情況下,intent發生了變化,就會進入onNewIntent中,這個方法的作用也是讓你來對舊的intent進行保存,對新的intent進行對應的處理。
注:可與用戶交互,我們稱為獨占設備
二.Activity啟動模式
1.使用AndroidManifest.xml聲明啟動模式
在清單文件中聲明 Activity 時,您可以使用元素的 ][launchMode屬性指定 Activity 應該如何與任務關聯。
您可以分配給 launchMode 屬性的啟動模式共有四種:
standard
singleTop
singleTask
singleInstance
先不用管他們具體的操作是什么,我們首先要知道這四種啟動模式可以分為兩大類:
standard和singleTop 該類啟動模式的activity可以被多次的實例化,它們的實例可以放到任何任務中,并且可以位于返回棧的任何位置。 singleTask和singleInstance 帶有此類啟動模式的activity,它們只能有一個實例存在,且實例只能存在于單獨的任務中。 standard:標準模式
默認啟動模式,啟動activity時直接創建新的實例并壓入啟動它的任務棧頂。
singleTop:棧頂復用模式
該模式唯一與standard不同的就是,如果啟動singleTop模式的activity時發現當前任務的棧頂已經存在著這個activity的實例,那么就不會創建新的實例,而是調用該實例的onNewIntent()方法。其他的跟標準模式一樣。
singleTask:棧內復用模式
這個模式有些特殊一點,我們先按使用情景介紹它,當我們將要啟動該模式的activity時,系統會判斷當前是否有它想要的任務棧:
沒有它要的任務棧 系統會新創建一個任務,并將該activity實例化作為該任務的根activity。
有它要的任務棧 這時候系統會找到該任務棧,如果任務棧里只有它自己則直接調用該activity實例的onNewIntent()方法。如果任務棧中它的上方還存在別的activity,那么這些activity會被全部彈出棧。
至于什么是“它想要的任務棧”,我們會在下面單獨分析。
singleInstance:單例模式 基本上跟singleTask相同,會為activity單獨創建一個任務并能夠復用。但是該模式的activity不允許其他activity跟自己存在于同一個任務中,由此 activity 啟動的任何 activity 均會被在其他的任務中打開。
2.使用Intent標志聲明啟動模式
此方式可以通過調用intent.addFlags(int flags)或者intent.setFlags(int flags)方法為Intent添加一個標志,用于為將要啟動的Activity聲明啟動模式。
在開始介紹前,先進行幾點掃盲科普:
一個Intent可以設置多個標志,這就是為啥有addflags()和setFlags()兩個方法的原因了。 為Intent設置標志的參數都是Intent類的靜態常量。 設置Intent標志不光只有設置activity啟動模式這一個功能,設置不同的參數還有其他功能。 Intent標志中可以對activity啟動模式進行操作的標志可多了,我們只介紹特別典型的三種。 Intent.FLAG_ACTIVITY_SINGLE_TOP 同AndroidManifest.xml方式中的singleTop啟動模式。
Intent.FLAG_ACTIVITY_NEW_TASK 同AndroidManifest.xml方式中的singleTask啟動模式。
Intent.FLAG_ACTIVITY_CLEAR_TOP 如果即將啟動的 activity 已經存在于當前任務棧中,則會彈出銷毀它上方的所有 activity,并調用該activity實例的onNewIntent()方法,而不是啟動該 Activity 的新實例。
跟singleTask有點像但不一樣,在AndroidManifest.xml方式中沒有與此對應的值。
singleTask默認就包含了FLAG_ACTIVITY_CLEAR_TOP的功能。
3.關聯任務
在分析singleTask時有提到過該模式下啟動activity前會去找“它想要的任務棧”,那么如何去找呢?這就引出了AndroidManifest.xml中標簽下的taskAffinity屬性。
taskAffinity 屬性
taskAffinity 屬性學名任務相關性,說白了其實就是這個參數可以指定當前activity所屬任務棧的名字,該屬性的值為字符串:
例:
android:taskAffinity="com.test.demo.task1"
如果你在標簽沒指定這個屬性,那么它就用標簽的taskAffinity屬性,如果標簽下也沒指定,它就應用包名當做默認值。
taskAffinity 與 singleTask
了解到taskAffinity屬性后我們在重新梳理一下singleTask啟動模式。
如果我們指定了taskAffinity屬性的值,那么就跟之前分析的一樣,創建新任務等等… 如果我們未指定taskAffinity屬性的值,新activity就與當前任務的taskAffinity屬性值一樣,所以新activity的實例會被放置到當前的任務棧中。 除了singleTask呢? 現在我們知道了taskAffinity屬性可以強行指定activity所屬的任務棧,那么這個屬性在其他啟動模式情況下是什么樣的呢?網上好多人都說沒有效果,我不信就親自測試了一下得出以下結論:
剛介紹 SingleInstance的時候說它跟singleTask一樣都會新建一個任務,既然singleTask是根據taskAffinity屬性來決定是否需要新建任務的,那么singleInstance是不是也需要指定這個屬性呢? 答案是否!只要啟動模式為singleInstance它一定會單獨開一個任務。
SingleTop模式下指定了taskAffinity屬性的值后,他就會神奇的切換到指定的那個任務棧中,除此之外跟原來一樣。
最神奇的就是Standard,它也同樣受到了taskAffinity屬性的影響,也會切換到指定的那個任務棧中,但當我們多次啟動這個activity時它不會再多次的創建實例,而是拉起了之前啟動過的實例,更特殊的是,其他三種啟動模式在復用之前實例時都會調用onNewIntent()方法,他卻不會調用該方法。
taskAffinity的其他作用
taskAffinity還有一個功能就是可以重新定向所屬任務,意思就是這個activity原來是屬于任務A的,當有一個跟該activity的taskAffinity屬性值相同的任務B被創建后,這個activity就會從任務A中轉移到任務B中。
想要實現這個功能我們還需要allowTaskReparenting屬性的配合:
我們在清單文件中給taskAffinity="A"的activity標簽下添加屬性android:allowTaskReparenting=true。 在taskAffinity="B"的任務下啟動這個activity,此時這個activity存在于任務B中。 當taskAffinity="A"的任務被創建或者被置于前臺,該activity將被轉移到其任務棧中,位于棧頂位置。
4.清理任務
如果用戶長時間離開任務,則系統會清除所有 Activity 的任務,根 Activity 除外。 當用戶再次返回到任務時,僅恢復根 Activity。系統這樣做的原因是,經過很長一段時間后,用戶可能已經放棄之前執行的操作,返回到任務是要開始執行新的操作。
您可以使用下列幾個 Activity 屬性修改此行為:
alwaysRetainTaskState 如果在任務的根 Activity 中將此屬性設置為 "true",則不會發生剛才所述的默認行為。即使在很長一段時間后,任務仍將所有 Activity 保留在其堆棧中。
clearTaskOnLaunch 如果在任務的根 Activity 中將此屬性設置為 "true",則每當用戶離開任務然后返回時,系統都會將堆棧清除到只剩下根 Activity。 即使只離開任務片刻時間,用戶也始終會返回到任務的初始狀態。
finishOnTaskLaunch 類似于clearTaskOnLaunch,但是更狠一些,當用戶離開任務再回來的時候,整個任務的activity都會清除,連根activity也是,相當于第一次啟動這個任務。
5.啟動模式的實際應用
個人覺得常見的四種啟動模式中要屬singleTop不是很好理解,其他的還好。
singleTop
singleTop模式的activity特點就是除了外部可以啟動它顯示信息外,它也可以用同樣的方式啟動自己更新顯示信息,這樣就減少了冗余代碼,降低了維護成本。
例:如果讓你設計一個帶有搜索應用的APP,主頁有一個搜索框,輸入信息點擊搜索按鈕進入結果頁顯示結果,為方便用戶使用,結果頁也有一個搜索框,跟主頁的搜索框功能一樣,你會怎么設計?
singleTask
這個啟動模式可以分為兩種情況:
未指定taskAffinity 此時該activity可以當應用中的某一模塊的入口處 有如下啟動流程,微信主頁 >> 聊天頁 >> 聊天設置頁 >> 用戶資料頁 >> 聊天頁,此時我們按下返回鍵直接回到了微信主頁。
指定了taskAffinity 如果利用該啟動模式新開了任務,在用戶的視角里就相當開了兩個應用(在任務管理器中會看到兩個最近應用),所以謹慎使用,我能想到的使用情況就是一個Word應用打開了兩份文檔。
singleInstance
這種情況下不管有多少個任務啟動它,它都會作為一個單獨任務存在著,這種模式極其特殊,謹慎使用。
例:撥號界面,鬧鐘界面。
一些常見的應用場景:
1、SingleTop適用于電商應用的商品詳情頁和新聞應用的正文頁之類頻繁在棧頂打開,并且每天都可能通過多個Notification打開的Activity
2、SingleTask則適用于每個應用的HomeActivity
3、SingleInstance則適用于支付和社會化這些需要在應用外啟動的Activity,Android系統自帶的Activity如電話、相機、鬧鐘也是SingleInstance
4、Actviity的Stack由ActivityManagerService管理,如果接管了一個在Application里實現保存Activity的Stack的項目,則說明這個毫無架構的項目每個Activity都是“萬能”的Activity
總結
以上是生活随笔為你收集整理的Activity的基本理解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 智能生活 App SDK 开发入门教程
- 下一篇: HDU 3966