Android學習筆記(三三) Activity生命週期
Android很大的應用場景是手機,有一些應用具有特別的優先級別,例如電話,同時裝置的記憶體是有限的。因在某些情況下系統將踢走activity,以便是否記憶體。因此在開發過程中,我們需要管理好activity的生命週期。右圖是Android的docs中提供的activity的時間觸發圖。
四大狀態
一般來講,某一時刻,Activity處在下面四個狀態之一:
Active:已由使用者啟動,正在前臺執行。
Paused:已由使用者啟動,正在執行且可視,但是由於提示或者其他覆蓋部分的螢幕。這是使用者可以看到activity,但不能與activity進行互動。例如有來電,給出接聽或者拒絕的選擇。
Stopped
Dead:activity沒有啟動或者終結,例如為了釋放緊缺的記憶體空間。
狀態轉變的事件
當狀態改變時,Android會提供1個或者多個觸發呼叫方法。我們通過重寫這些方法來實現我們的處理。
public class MyActivity extends Activity{ protected void onCreate(Bundle savedInstanceState){….. } protected void onStart(){….. } protected void onRestart(){….. } protected void onResume(){….. } protected void onPause(){….. } protected void onStop(){….. } protected void onDestroy(){….. } }
onCreate()和onDestroy()
onCreate(Bundle),在以前我們經常在onCreate()中載入XML的佈局檔案。在onCreate()中,對UI進行初始化,並完成其他初始化(只需的處理一次,例如繫結某些監聽器)。onCreate()在下面三種情況中會被呼叫:
- Activity首次啟動,也就是自系統加電後第一次啟動,Bundle引數為null
- 如果Acivity曾執行,並後來被killed掉,在呼叫時引數是onSaveInstanceState()的Bundle。
- Activity已經執行,但因為不同裝置的狀態需要不同的資源,例如豎屏改為橫屏,acivity將會re-create,而onCreate()會被呼叫
onDestroy():在activity生命週期的最後,即關閉時被呼叫,可以是通過finish()由activity主動關閉,也可能是因為系統需要記憶體而被動關閉。注意如果RAM緊缺的時候,可能onDestroy()不會被呼叫,但acvitiy仍會被關閉。在onDestroy()中對onCreate()中獲得的資源進行釋放。
onStart(),onRestart()和onStop()
onStart()一個activity第一次被呼叫時,將在前臺呈現UI時或者被隱藏後重新在前臺呈現時呼叫,即當用戶可以看見或者重新看見activity時呼叫。
onReStart()在一個activity被stop後重啟時呼叫。
onStop()就是在activity的狀態變為stopped狀態時呼叫。
onPause()和onResume()
onResume()在activity成為前臺程式時呼叫,也就是使用者可和activity互動時呼叫。當activity初次呼叫,或者從一個stopped狀態中恢復,先是UI可視-onStart(),然後UI可互動-onResume()。當一個pop-up對話方塊(例如一個來電,將導致acivity進入Paused狀態)消除的情況會觸發onResume(),因為Paused的狀態中UI是可視,只是被覆蓋而無效,因此不會有UI可視-onStart()呼叫,只有UI可互動-onResume()呼叫。在onResume()中可進行UI的重新整理。
任何使得使用者不在關注你的Activity,例如其他activity啟動,onPause()被呼叫,在這裡我們可以undo在onResume中do的,停止後臺程序,釋放原來佔用的資源(例如攝像頭),一旦onPause()被呼叫後,當acivity被系統killed的時候,不會收到事件提醒,即不會觸發onDestory()。
場景例子
我們通過考察activity中調起令一個activity的情況來看看activity的狀態變化事件。
場景1:如果我們在一個activity(activity1)中通過intent啟動另一個activity(activity2),那麼觸發的過程是:
activity1-onPause()->activity2-onCreate()->activity2-onStart()->activity2-onResume()->activity1-onStop()
activity1:失去了使用者的焦點,無法和使用者進行互動,被activity2覆蓋,呼叫了onPause(),然後是activity2的啟動呼叫過程,通常activity2不是覆蓋部分,而且完全佔據螢幕,由此activity1被隱藏,activity1進入了Stopped狀態,呼叫activity1-onStop()。如果acvity2已對話方塊的方式,而不是全螢幕,即activity1不會並因此,仍然保留在Paused狀態,則不會觸發activity1-onStop()。
activity2:對於一個activity的啟動順序為初始化onCreate() -> 使用者可視onStart() -> 使用者可互動(獲得焦點)onResume()
場景2:我們按選單的返回鍵,從activity2退出,並恢復為activity1
activity2-onPause() -> activity1-onRestart() -> activity1-onStart() -> activity1-onResume() ->activity2-onStop() -> activity2-onDestory()
activity1:在場景1中進入Stopped狀態,重新恢復,進入onRestart()狀態,UI可視onStart(),獲得焦點使用者可互動onResume()
activity2:按返回鍵,acivity將被登出,根據android給出來的圖,依次進行onPause()失去焦點不可互動->onStop()不可視->on Destory()被關閉。
在mars-android的視訊教學中通過一個activity的stack,成為task來解釋這種依次調起activity的情形。但是在我下載的更新的reference中,在相應的html中已經刪除了相關的內容。但在另外的文件中找到Task的描述。當用戶從一個activity跳到一個activity,可以是不同的app,Android系統記錄activity的執行緒導航歷史,這就是activity stack,也稱為back stack。當前螢幕最前面的UI就是stack最上面的一個activity,當這個activity調起一個新的activity時,這個activity-new將加入這個stack,作為stack最上面的元素,當用戶按下BACK鍵時,將最上面也就是當前UI顯示的activity-new從stack中拿走,並刪除這個activity-new(進入Deaded狀態)。這樣可以很好地理解Android處理按下BACK鍵的情況,這些activity是按一定順序,不可改變(當然如果我們使用finish()可以刪除其中某個acitivity,從stack中去除),處理方式是stack的先進後出。
資料儲存
Android可能會因為記憶體的緣故踢走你的activiy,activiy會儲存一些狀態,利用這我們可以儲存一些我們所需的資料。儲存資料的方式為onSaveInstanceState(),要注意,由於activity會頻繁地執行之,所以一定要保證高效,只將我們的data存放如Bundle。獲取資料有兩個途徑,一是onCreate(Bundle)中的引數攜帶該data,二是在onRestoreInstanceState()。我們可以選擇所需的資料,這個資料甚至可以是一個callback。
Pop-up對話方塊
在我們之前的學習中都是新的activity完全覆蓋原activity,另一種情況是部分覆蓋,使原來的activity進入Paused狀態,而不是Stopped,如右圖所示。程式程式碼和普通沒有什麼不同,關鍵是AndroidManifest.xml。如下:
<activity android:name=".MyActivity" android:label="@string/myactivity"android:theme="@android:style/Theme.Dialog" />