原文地址http://www.cnblogs.com/lwbqqyumidi/p/3769113.html
類似地址http://blog.csdn.net/liuhe688/article/details/6733407
Android官方文檔和其他不少資料都對Activity生命周期進行了詳細介紹,在結(jié)合資料和項目開發(fā)過程中遇到的問題,本文將對Activity生命周期進行一次總結(jié)。
Activity是由Activity棧進管理,當來到一個新的Activity后,此Activity將被加入到Activity棧頂,之前的Activity位于此Activity底部。Acitivity一般意義上有四種狀態(tài):
1.當Activity位于棧頂時,此時正好處于屏幕最前方,此時處于運行狀態(tài);
2.當Activity失去了焦點但仍然對用于可見(如棧頂?shù)腁ctivity是透明的或者棧頂Activity并不是鋪滿整個手機屏幕),此時處于暫停狀態(tài);
3.當Activity被其他Activity完全遮擋,此時此Activity對用戶不可見,此時處于停止狀態(tài);
4.當Activity由于人為或系統(tǒng)原因(如低內(nèi)存等)被銷毀,此時處于銷毀狀態(tài);
在每個不同的狀態(tài)階段,Adnroid系統(tǒng)對Activity內(nèi)相應的方法進行了回調(diào)。因此,我們在程序中寫Activity時,一般都是繼承Activity類并重寫相應的回調(diào)方法。
先貼一張來自官方文檔(http://developer.android.com/reference/android/app/Activity.html)的圖,相信大家都看到過。
圖中詳細給出了Activity整個生命周期的過程,以及在不同的狀態(tài)期間相應的回調(diào)方法。
圖中需要注意一下幾點:
1.Activity實例是由系統(tǒng)自動創(chuàng)建,并在不同的狀態(tài)期間回調(diào)相應的方法。一個最簡單的完整的Activity生命周期會按照如下順序回調(diào):onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy。稱之為entire lifetime。
2.當執(zhí)行onStart回調(diào)方法時,Activity開始被用戶所見(也就是說,onCreate時用戶是看不到此Activity的,那用戶看到的是哪個?當然是此Activity之前的那個Activity),一直到onStop之前,此階段Activity都是被用戶可見,稱之為visible lifetime。
3.當執(zhí)行到onResume回調(diào)方法時,Activity可以響應用戶交互,一直到onPause方法之前,此階段Activity稱之為foreground lifetime。
在實際應用場景中,假設A Activity位于棧頂,此時用戶操作,從A Activity跳轉(zhuǎn)到B Activity。那么對AB來說,具體會回調(diào)哪些生命周期中的方法呢?回調(diào)方法的具體回調(diào)順序又是怎么樣的呢?
開始時,A被實例化,執(zhí)行的回調(diào)有A:onCreate -> A:onStart -> A:onResume。
當用戶點擊A中按鈕來到B時,假設B全部遮擋住了A,將依次執(zhí)行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop。
此時如果點擊Back鍵,將依次執(zhí)行B:onPause -> A:onRestart -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。
至此,Activity棧中只有A。在Android中,有兩個按鍵在影響Activity生命周期這塊需要格外區(qū)分下,即Back鍵和Home鍵。我們先直接看下實驗結(jié)果:
此時如果按下Back鍵,系統(tǒng)返回到桌面,并依次執(zhí)行A:onPause -> A:onStop -> A:onDestroy。
此時如果按下Home鍵(非長按),系統(tǒng)返回到桌面,并依次執(zhí)行A:onPause -> A:onStop。由此可見,Back鍵和Home鍵主要區(qū)別在于是否會執(zhí)行onDestroy。
此時如果長按Home鍵,不同手機可能彈出不同內(nèi)容,Activity生命周期未發(fā)生變化(由小米2s測的,不知道其他手機是否會對Activity生命周期有影響)。
由于Android本身的特性,使得現(xiàn)在不少應用都沒有直接退出應用程序的功能,按照一般的邏輯,當Activity棧中有且只有一個Activity時,當按下Back鍵此Activity會執(zhí)行onDestroy,那么下次點擊此應用程圖標將從重新啟動,因此,當前不少應用程序都是采取如Home鍵的效果,當點擊了Back鍵,系統(tǒng)返回到桌面,然后點擊應用程序圖標,直接回到之前的Activity界面,這種效果是怎么實現(xiàn)的呢?
通過重寫按下Back鍵的回調(diào)函數(shù),轉(zhuǎn)成Home鍵的效果即可。
@Overridepublic 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順序和狀態(tài)。
在之前的項目開發(fā)過程中,當時遇到一個很奇怪的問題:手機上的“開發(fā)者選項”中有一個“不保留活動”的設置,當開啟此設置,手機上的設置提示是“用戶離開后即銷毀每個活動”,開啟后,對于其他的應用程序是從A Acticity到B Activity,然后Back鍵回到A,此時,其他應用程序只是先白屏(有可能黑屏等,取決于主題設置)一下,然后A開始可見,但是我的應用程序中出現(xiàn)的一個結(jié)果卻是直接返回到了桌面。一開始百思不得其解。最后終于定位出問題。首先,我們需要明確開啟此設置項后對Activity生命周期的影響。開啟此設置項后,當A到B時,假設B全部遮擋住了A,將依次執(zhí)行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop -> A:onDestroy。是的,A在系統(tǒng)原本的生命周期回調(diào)中增加了onDestroy。此即“用戶離開后即銷毀每個活動”的含義。但此時需要注意的是,只要沒有認為的調(diào)用A的finish()方法,雖然A執(zhí)行了onDestroy,但Activity棧中依然保留有A,此時B處于棧頂。那么在B中按Back鍵回到A時,將依次執(zhí)行:B:onPause -> A:onCreate -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。沒錯,A從onCreate開始執(zhí)行了。此處也就解釋了為什么A可能會出現(xiàn)白屏(或黑屏等)一下的原因了。
那么為什么我的應用程序會跟其他應用程序出現(xiàn)不一樣呢?最后定為出問題在于當時我的應用程序中為了做到完全退出應用程序效果,專門使用了一個Activity棧去維護Activity(當時是借鑒了網(wǎng)上的此類實現(xiàn)方案,現(xiàn)在想想,實在沒必要,且不說Android本身特性決定了沒必要通過如此方法去達到退出效果,僅僅是此方法本身也存在很大的問題,現(xiàn)在在網(wǎng)上依然能見到有不少文章說到應用程序退出可以使用此方法,哎。。),在onCreate中入棧,onDestroy出棧,調(diào)用了如下方法:
1 // 結(jié)束Activity&從堆棧中移除2 AppManager.getAppManager().finishActivity(this);
其中,AppManager中finishActivity函數(shù)具體定義是:
1 /** 2 * 結(jié)束指定的Activity 3 */ 4 public void finishActivity(Activity activity) { 5 if (activity != null) { 6 activityStack.remove(activity); 7 activity.finish(); 8 activity = null; 9 }10 }
至此,相信大家應該看出問題的所在了吧。
沒錯,問題在于執(zhí)行了activity的finish()方法??! activity的finish()方法至少有兩個層面含義,1.將此Activity從Activity棧中移除,2.調(diào)用了此Activity的onDestroy方法。對于不開啟“不保留活動”的設置項,實際上也沒什么影響,但是一旦開啟此設置,問題顯露無疑。開啟此此設置后,正常情況下離開A,即使執(zhí)行了A的onDestroy,Activity棧中還是有A的,但是我這樣寫后,finish()方法一執(zhí)行,Activity棧中就沒有A了,因此,當點擊Back鍵時,Activity棧中已經(jīng)沒有此應用的任何Activity了,直接來到了手機桌面。
可能,有些人會說,我就是要通過此種方法想去完全退出應用程序,同時希望自己的Activity棧和系統(tǒng)中Activity棧保持一致,怎么辦呢?
在此,可以通過如下改寫去實現(xiàn):
/*** 結(jié)束指定的Activity */public void finishActivity(Activity activity) { if (activity != null) { // 為與系統(tǒng)Activity棧保持一致,且考慮到手機設置項里的"不保留活動"選項引起的Activity生命周期調(diào)用onDestroy()方法所帶來的問題,此處需要作出如下修正 if(activity.isFinishing()){ activityStack.remove(activity); //activity.finish(); activity = null; } }}
以此謹記!
-------------------------------------------------
此外,對于不同的啟動模式或Intent Flags或操作行為(如橫豎屏切換)等有可能會影響到Activity生命周期,此類問題將放在后續(xù)相關(guān)文章中進行總結(jié)。
聯(lián)系客服