標籤:
Android很大的應用情境是手機,有一些應用具有特別的優先順序別,例如電話,同時裝置的記憶體是有限的。因在某些情況下系統將踢走activity,以便是否記憶體。因此在開發過程中,我們需要管理好activity的生命週期。右圖是Android的docs中提供的activity的時間觸發圖。
四大狀態
一般來講,某一時刻,Activity處在下面四個狀態之一:
Active:已由使用者啟動,正在前台運行。
Paused:已由使用者啟動,正在運行且可視,但是由於提示或者其他覆蓋部分的螢幕。這是使用者可以看到activity,但不能與activity進行互動。例如有來電,給出接聽或者拒絕的選擇。
Stopped:已由使用者啟動,正在運行,但是由於其他activity而被隱藏,無法向使用者直接呈現有效資訊,但是可以通過notification進行通訊。
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" />
相關連結:我的Andriod開發相關文章
Android學習筆記(三三):Activity生命週期