Android Activity生命週期

Activity是由Activity棧進管理,當來到一個新的Activity後,此Activity將被加入到Activity棧頂,以前的Activity位於此Activity底部。Acitivity通常意義上有四種狀態:html

1.當Activity位於棧頂時,此時正好處於屏幕最前方,此時處於運行狀態android

2.當Activity失去了焦點但仍然對用於可見(如棧頂的Activity是透明的或者棧頂Activity並非鋪滿整個手機屏幕),此時處於暫停狀態app

3.當Activity被其餘Activity徹底遮擋,此時此Activity對用戶不可見,此時處於中止狀態ide

4.當Activity因爲人爲或系統緣由(如低內存等)被銷燬,此時處於銷燬狀態;函數

在每一個不一樣的狀態階段,Adnroid系統對Activity內相應的方法進行了回調。所以,咱們在程序中寫Activity時,通常都是繼承Activity類並重寫相應的回調方法。this

先貼一張來自官方文檔(http://developer.android.com/reference/android/app/Activity.html)的圖,相信你們都看到過。spa

 

 

 

 

圖中詳細給出了Activity整個生命週期的過程,以及在不一樣的狀態期間相應的回調方法。code

 

圖中須要注意一下幾點:htm

 

1.Activity實例是由系統自動建立,並在不一樣的狀態期間回調相應的方法。 一個最簡單的完整的Activity生命週期會按照以下順序回調:onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy。稱之爲entire lifetime。blog

 

2.當執行onStart回調方法時,Activity開始被用戶所見(也就是 說,onCreate時用戶是看不到此Activity的,那用戶看到的是哪一個?固然是此Activity以前的那個Activity),一直到 onStop以前,此階段Activity都是被用戶可見,稱之爲visible lifetime。

 

3.當執行到onResume回調方法時,Activity能夠響應用戶交互,一直到onPause方法以前,此階段Activity稱之爲foreground lifetime。

 

在實際應用場景中,假設A Activity位於棧頂,此時用戶操做,從A Activity跳轉到B Activity。那麼對AB來講,具體會回調哪些生命週期中的方法呢?回調方法的具體回調順序又是怎麼樣的呢?

 

開始時,A被實例化,執行的回調有A:onCreate -> A:onStart -> A:onResume。

 

當用戶點擊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生命週期有影響)。

 

因爲Android自己的特性,使得如今很多應 用都沒有直接退出應用程序的功能,按照通常的邏輯,當Activity棧中有且只有一個Activity時,當按下Back鍵此Activity會執行 onDestroy,那麼下次點擊此應用程圖標將從從新啓動,所以,當前很多應用程序都是採起如Home鍵的效果,當點擊了Back鍵,系統返回到桌面, 而後點擊應用程序圖標,直接回到以前的Activity界面,這種效果是怎麼實現的呢?

 

經過重寫按下Back鍵的回調函數,轉成Home鍵的效果便可。

 

複製代碼
@Override public void onBackPressed() { Intent home = new Intent(Intent.ACTION_MAIN); home.addCategory(Intent.CATEGORY_HOME); startActivity(home); }
複製代碼

 

固然,此種方式經過Home鍵效果強行影響到Back鍵對Activity生命週期的影響。注意,此方法只是針對按Back鍵須要退回到桌面時的Activity且達到Home效果才重寫。

 

或者,爲達到此類效果,Activity實際上提供了直接的方法。

 

1 activity.moveTaskToBack(true);

 

moveTaskToBack()此方法直接將當前Activity所在的Task移到後臺,同時保留activity順序和狀態。

 

 

 

在以前的項目開發過程當中,當時遇到一個很奇怪的問題:手機上的「開發者選項」中有一個「不保留活動」的設置,當開啓此設置,手機上的設置提示是「用戶離開後即銷燬每一個活動」, 開啓後,對於其餘的應用程序是從A Acticity到B Activity,而後Back鍵回到A,此時,其餘應用程序只是先白屏(有可能黑屏等,取決於主題設置)一下,而後A開始可見,可是個人應用程序中出現 的一個結果倒是直接返回到了桌面。一開始百思不得其解。最後終於定位出問題。首先,咱們須要明確開啓此設置項後對Activity生命週期的影響。開 啓此設置項後,當A到B時,假設B所有遮擋住了A,將依次執行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop -> A:onDestroy。是的,A在系統本來的生命週期回調中增長了onDestroy。此即「用戶離開後即銷燬每一個活動」的含義。但此時須要注意的是,只要沒有認爲的調用A的finish()方法,雖然A執行了onDestroy,但Activity棧中依然保留有A,此時B處於棧頂。那麼在B中按Back鍵回到A時,將依次執行:B:onPause -> A:onCreate -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。沒錯,A從onCreate開始執行了。此處也就解釋了爲何A可能會出現白屏(或黑屏等)一下的緣由了。

 

那麼爲何個人應用程序會跟其餘應用程序出現不 同樣呢?最後定爲出問題在於當時個人應用程序中爲了作到徹底退出應用程序效果,專門使用了一個Activity棧去維護Activity(當時是借鑑了網 上的此類實現方案,如今想一想,實在不必,且不說Android自己特性決定了不必經過如此方法去達到退出效果,僅僅是此方法自己也存在很大的問題,現 在在網上依然能見到有很多文章說到應用程序退出可使用此方法,哎。。),在onCreate中入棧,onDestroy出棧,調用了以下方法

 

1 // 結束Activity&從堆棧中移除 2 AppManager.getAppManager().finishActivity(this);

 

其中,AppManager中finishActivity函數具體定義是:

 

複製代碼
 1 /**  2  * 結束指定的Activity  3 */  4 public void finishActivity(Activity activity) {  5 if (activity != null) {  6  activityStack.remove(activity);  7  activity.finish();  8 activity = null;  9  } 10 }
複製代碼

 

至此,相信你們應該看出問題的所在了吧。

 

沒錯,問題在於執行了 activity的finish()方法!! activity的finish()方法至少有兩個層面含義,1.將此Activity從Activity棧中移除,2.調用了此Activity的 onDestroy方法。對於不開啓「不保留活動」的設置項,實際上也沒什麼影響,可是一旦開啓此設置,問題顯露無疑。開啓此此設置後,正常狀況下離開 A,即便執行了A的onDestroy,Activity棧中仍是有A的,可是我這樣寫後,finish()方法一執行,Activity棧中就沒有A 了,所以,當點擊Back鍵時,Activity棧中已經沒有此應用的任何Activity了,直接來到了手機桌面。

 

可能,有些人會說,我就是要經過此種方法想去徹底退出應用程序,同時但願本身的Activity棧和系統中Activity棧保持一致,怎麼辦呢?

 

在此,能夠經過以下改寫去實現:

 

 

 

複製代碼
/** * 結束指定的Activity */ public void finishActivity(Activity activity) { if (activity != null) { // 爲與系統Activity棧保持一致,且考慮到手機設置項裏的"不保留活動"選項引發的Activity生命週期調用onDestroy()方法所帶來的問題,此處須要做出以下修正 if(activity.isFinishing()){ activityStack.remove(activity); //activity.finish(); activity = null; } } }
複製代碼

 

 

 

以此謹記!

 

-------------------------------------------------

 

此外,對於不一樣的啓動模式或Intent Flags或操做行爲(如橫豎屏切換)等有可能會影響到Activity生命週期,此類問題將放在後續相關文章中進行總結。

 

轉載:Corn http://www.cnblogs.com/lwbqqyumidi/p/3769113.html

相關文章
相關標籤/搜索