深入剖析Android四大組件(一)——Activity生命周期具體解釋
1.管理Activity的生命周期
不管是正在執行的Activity還是沒有執行的Activity,它們都接受Android的框架管理,這使得Activity處於不同的生命周期。
①Activity的3種狀態
通過回調方法來管理Activity的生命周期對於開發一個健壯而且靈活的應用程序是很關鍵的。
Activity的生命周期直接影響到它與其它Activity,任務以及棧的關系。
Activity存在3種狀態。各自是resumed,paused和stopped。
?resumed:指Activity在屏幕前臺而且擁實用戶焦點的狀態。這個狀態有時也稱為“正在執行”
paused:指還有一個
stopped:指前一個Activity被還有一個Activity全然遮蔽(前一個Activity當前在後臺中)。
一個處於stopped狀態的Activity仍然是存活的(這個Activity對象在內存中被保留,它維護全部狀態和成員信息,但沒有依附窗體管理器)。然而。它卻不再顯示給用戶,而且在內存極低時會被系統殺掉。
假設一個Activity處於paused或stopped狀態,那麽系統會從內存中丟掉它。這能夠通過調用它的finish()方法來實現,或者簡單一點,通過殺掉它的進程來實現。
當Activity又一次打開(在它結束或者被殺掉之後)時,它就必須被又一次創建。
②實現Activity的生命周期回調
當Activity發生狀態轉變時,它會通過回調方法來得到通知,我們能夠重寫全部這些回調方法完畢適當的工作。
當Activity狀態發生改變時,Activity的框架包括每個主要的生命周期方法,例如以下列代碼所看到的:
@Override
public void onCreate(Bundle savedInstanceState){
//指示這個Activity正在被創建
super.onCreate(saveInstanceState);
//完畢一些任務
}
@Override
protected void onStart(){
//這個Activity正在變為可見
super.onStart();
//完畢一些任務
}
@Override
protected vodi onResume(){
//這個Activity已經變為可見
//如今是resumed狀態
super.onResume();
//完畢一些任務
}
@Override
oritected void onPause(){
//還有一個Activity獲得焦點並且當前的Activity失去焦點
//也就是當前Activity被還有一個Activity部分或者所有覆蓋
//當前Activity失去焦點的時候調用
//這個Activity如今處於paused狀態
super.onPause();
//完畢一些任務
}
@Override
protected void onStop(){
//這個Activity不再可見的時候調用
//當前Activity處於stopped狀態
super.onStop();
//完畢一些任務
}
@Override
protected void onDestory(){
//這個Activity已經被銷毀
super.onDestory();
//完畢一些任務
}
建議:通常,在實現這些生命周期方法時,必須先調用超類的實現(比方調用super.XXX)。綜上所述,以上這些方法定義了Activity的整個生命周期。通過實現這些方法,我們就能監視Activity生命周期中的3個嵌套循環,詳細例如以下所看到的。
?Activity的整個生命周期發生在調用onCreate()和調用onDestory()之間。
在onCreate()中,Activity應該設置“全局”狀態(比方定義布局),而且在onDestory()中釋放其余資源。比如,假設Activity有一個後臺執行的線程從網絡上下載數據,那麽它應該在onCreate()中創建這個線程,而且在onDestory()停止該線程。
Activity的可見生命周期發生在調用onStart()和調用onStop()之間。在這個過程中,用戶能夠看到這個Activityd在屏幕中而且能夠與之交互。比如。當一個新Activity啟動而且前一個Activity不再可見的時候,onStop()就被調用了。在這兩個方法之間,能夠維護須要顯示給用戶的Activity資源。比如,能夠在onStart()方法中註冊一個廣播接收器去監視影響UI的變化,當用戶看不到顯示的東西時。則在onStop()註銷它。在Activity的整個生命周期中。當Activity在可見和隱藏之間切換時,系統就會多次調用onStart()和onStop()方法。
Activity的前臺生命周期發生在調用onResume和調用onPause()之間。須要說明的是。在這期間,Activity在屏幕中全部其它Activity的前面而且擁實用戶焦點。
普通情況下。Activity能夠被頻繁轉換。
比如。當設備休眠或者顯示一個對話框時,onPause()就會被調用。
對於以上知識,為了方便讀者理解並理順它們之間的內在關系,我們用一張圖來直觀地描寫敘述。例如以下圖:
上圖為Activity生命周期的演化過程
順便也列出一張表。描寫敘述了在Activity的整個生命周期裏定位的每個回調方法以及其細節,以及回調方法完畢後系統能否夠停止這個Activity等。
方法 | 描寫敘述 | 調用後能否夠被殺掉 | 下一步操作 |
onCreate() | 當Activity第一次被創建時調用。此處能夠做全部的一般靜態設置,比方創建視圖,綁定列表數據等。
|
否 | onStart() |
onRestart() | Activity被停止後。再次啟動之前調用。 | 否 | onStart() |
onStart() | 在Activity對用戶可見之前被調用。
|
否 | onResume()或者onStop() |
onResume() | 在Activity開始與用戶交互之前被調用。在這裏,該Activity位於Activity棧頂。開始與用戶交互。 須要註意的是,此時當前Activity處於resumed狀態。這個狀態下Activity是可見的。 |
否 | onPause() |
onPause() | 當系統正在恢復還有一個Activity的時候被調用。這種方法通經常使用於提交未保存的數據,停止動畫以及可能 消耗CPU的事情等。這些應該高效地完畢,由於下一個Activity在這種方法沒有返回之前不會被執行。假設Activity回到前臺,則下一步操作為調用onResume()。假設Activity變得不可見。則調用onStop(). | 是 | onResume()或者onStop() |
onStop() | 當Activity對用戶不再可見的時候調用。 這會發生,是由於它正在被銷毀或者還有一個Activity(能夠是已經存在的或者新的)被執行而且覆蓋了它。 |
是 | onRestart()或者onDestory() |
onDestory() | 該Activity被銷毀之前調用。這個Activity收到的終於調用。它能夠是由於Activity正在結束(調用finish()),或者是由於心痛為保護空間而面臨銷毀這個Activity的實例而調用。能夠通過isFinishing()方法區分這兩種情況。 | 是 | 無 |
2.保存和協調Activity
在Activity切換狀態的時候。可能須要保存一些中間狀態。比方控件的選擇狀態等。以便當它又一次被顯示出來時仍能夠恢復到之前推出的狀態。
①保存Activity狀態
當一個Activity被暫停或者停止的時候。它的狀態被保留。由於當它被暫停或者停止的時候,Activity對象仍然駐留在內存中——全部有關它的成員變量和當前狀態的信息仍然存在。因此,全部用戶導致的Activity的變化就被保存在內存中。而當這個Activity返回到前臺時(當它被恢復時)。這些變化仍然在內存中。
然而。當系統為恢復內存而銷毀一個Activity時,這個Activity對象也就被銷毀了。此時系統就不能簡單地恢復它並持有它的完整狀態。
取而代之的是。假設用戶再次導航到這裏,系統就必須又一次創建這個Activity對象,可是用戶不知道系統已經銷毀了該Activity而如今又又一次創建了它。因此,用戶可能覺得這個Activity就是之前的那個Activity。在這樣的情況下,我們能夠通過實現一個附加的同意保存我們Activity狀態信息的回調方法,而將關於Activity狀態的重要信息保留下來,然後當系統又一次創建這個Activity的時候,再去又一次存儲它。
保存Activity當前狀態信心的回調方法是onSaveInstanceState()。系統在Activity被銷毀之前調用此方法,並再傳一個Bundle對象。這個Bundle對象能夠存儲Activity狀態(以名稱--值對的形式)信息,能夠使用像putString()之類的方法。
那麽,假設系統停止掉Activity進程。而且用戶又又一次啟動該Activity,那麽系統進程會將這個Bundle對象傳遞給onCreate(),這樣就能夠恢復onSaveInstanceState()中保存的Activity狀態了。假設沒有為恢復的狀態信息,那麽傳給onCreate()的Bundle對象則是null。
註意:由於保存應用程序狀態不是必要的行為。所以不能確保onSaveInstanceState()在Activity被銷毀之前調用(比如當用戶由於明白關閉而使用BACK鍵離開該Activity時)。假設這種方法被調用,那麽它將總是在onStop()並有可能在onPause()之前調用。
盡管如此,但即使你沒有實現onSaveInstanceState()方法,也還是有一些Activity的狀態通過Activity類默認實現的onSaveInstanceState()方法恢復。特別是,默認實現會為布局中的每個視圖調用onSaveInstanceState(),同意每個視圖提供它們自己要保存的信息。差點兒每個Android框架中的部件都會適當地實現這種方法。這樣一來,當Activity被又一次創建的時候,不論什麽一個對於UI可見的變化都被自己主動保存和恢復。比如,EditText空間保存用戶輸入的全部文本,CheckBox空間保存它是否被選擇。而我們須要做的僅僅是為全部想要保存狀態的空間提供一個唯一的ID(借助android:id屬性)。
雖然onSaveInstanceState()的默認實現會保存這個Activity UI的實用信息,可是我們可能仍然須要重寫它以便保存額外的信息。比如。我們可能須要保存在整個Activity生命周期中變化的成員變量的值。因為默認實現的onSaveInstanceState()幫助保存UI的狀態,所以假設重寫這種方法是為了保存額外的信息。那麽就應該在做不論什麽工作之 前先調用超類的onSaveInstanceState()方法。
註意:由於我們不能保證onSaveInstanceState()會被調用。所以使用它僅僅能夠記錄Activity的瞬間狀態,而不能用來保存持久數據。相反,當用戶離開這個Activity時,應該用onPause()保存持久數據(比如那些應該保存到數據庫中的數據)。
下圖直觀的展現了Android是怎樣保存這些狀態的。
上圖為Android保存這些狀態的流程示意圖
假設須要恢復保存的狀態,應該都知道Activity的生命周期中有一個onCreate()方法中傳遞了一個Bundle對象。詳細恢復的代碼例如以下所看到的:
@Override public void onCreate(Bundle saveInstanceState){ super.onCreate(saveInstanceState); if(saveInstanceState!=null){
//獲取你保存的狀態信息 } }
這樣一來,當界面被創建的時候,Activity仍然能找到用戶最後操作的數據。
須要註意的是,憂郁我們不能保證是否存在保存的狀態。因此須要一個推斷來鑒別if(saveInstanceState!=null)。
②協調Activity
當一個Activity啟動還有一個Activity的時候,它們都會經歷各自的生命周期的改變。第一個Activity被暫停或停止(假設它仍然可見,就不會被停止)時。還有一個Activity被創建。而這些Activity共享的數據被保存到磁盤或別的地方。
生命周期回調的順序要非常好地定義,尤其是當兩個Activity在同一個過程中而且一個正在啟動還有一個的時候。
以下給出了Activity A啟動Activity B的順序。
第一,Activity A運行onPause()方法。
第二,Activity B順序運行onCreate(),onStart(),onResume()方法(Activity如今獲得用戶焦點)。
第三,假設Activity A在屏幕中不再可見,則它的onStop()方法就會被運行。
這個生命周期回調的序列同意我們管理從一個Activity到還有一個Activity轉變的信息。
比如。假如必需要寫數據庫,則當第一個Activity停止的時候,那麽緊跟著的Activity就能夠讀取那個停止了的Activity。這種話,我們就應該在onPause()中而不是在onStop()中寫數據庫。
3.用實例說話
這個實例很easy,它包括兩個Activity,它們都實現了全部的生命周期回調接口,而且還實現了相關的Activity狀態保存與狀態恢復的回調方法。此外。我們還能夠從一個Activity導航到還有一個Activity上。詳細的操作過程例如以下所看到的。
①創建一個名為ActivityLife的project。包名為helloworld.liyuanjing.example.com.activitylife。
創建完畢後,我們就在原有的基礎上加入一個新類SecondActivity,它繼承自Activity類。
此時Androidproject中就擁有兩個Java代碼文件,它們各自是MainActivity.java和SecondActivity.java。如今。這兩個代碼都實現生命周期的全部方法。並在各個方法中加入日誌。加入日誌的方法例如以下:
Log.e(TAG, message);
②將新增的類SecondActivity聲明到AndroidManifest.xml文件裏去,這一步很重要。假設沒有這一步,就無法啟動SecondActivity。聲明代碼例如以下:
<activity android:name=".SecondActivity"></activity>
在AndroidManifest.xml中聲明一個Activity有相當多的講究,這裏僅僅做簡單配置上去,從而使得我們的Activity能夠正常啟動。如需深入清單文件能夠到http://blog.csdn.net/column/details/androidmanifest.html該專欄下一探到底。
再者,為了實現從MainActivity上啟動SecondActivity,我們須要在默認的布局文件(activity_main)中加入一個button。
而且實現它的單擊事件。在該事件中。啟動SecondActivity。改動後的布局代碼例如以下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<Button
android:id="@+id/mybut"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="To SecondActivity"/>
</LinearLayout>
改動後的MainActivity的代碼例如以下:
public class MainActivity extends Activity { public static final String TAG="MainActivity"; private Button mybut=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.e(TAG, "MainActivity::onCreate()"); this.mybut=(Button)findViewById(R.id.mybut); this.mybut.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this,SecondActivity.class)); } }); } @Override protected void onStart() { super.onStart(); Log.e(TAG, "MainActivity::onStart()"); } @Override protected void onResume() { super.onResume(); Log.e(TAG, "MainActivity::onResume()"); } @Override protected void onPause() { super.onPause(); Log.e(TAG, "MainActivity::onPause()"); } @Override protected void onStop() { super.onStop(); Log.e(TAG, "MainActivity::onStop()"); } @Override protected void onDestroy() { super.onDestroy(); Log.e(TAG, "MainActivity::onDestroy()"); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Log.e(TAG, "MainActivity::onSaveInstanceState()"); } }
SecondActivity的代碼例如以下:
public class SecondActivity extends Activity { public static final String TAG="SecondActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.e(TAG, "SecondActivity::onCreate()"); } @Override protected void onResume() { super.onResume(); Log.e(TAG, "SecondActivity::onResume()"); } @Override protected void onStart() { super.onStart(); Log.e(TAG, "SecondActivity::onStart()"); } @Override protected void onPause() { super.onPause(); Log.e(TAG, "SecondActivity::onPause()"); } @Override protected void onStop() { super.onStop(); Log.e(TAG, "SecondActivity::onStop()"); } @Override protected void onDestroy() { super.onDestroy(); Log.e(TAG, "SecondActivity::onDestroy()"); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Log.e(TAG, "SecondActivity::onSaveInstanceState()"); } }
③編譯執行project,註意觀察日誌。等到應用程序展現出來的時候,就能夠觀察到例如以下圖所看到的的日誌信息:
出現這種界面就說明,一個Activity從啟動到展示完畢經歷了從onCreate()到onStart()。在再到onResume的3個階段。
④單擊“導航”button,也就是布局文件那個button,啟動SecondActivity,看看有什麽樣的日誌輸出,例如以下圖:
此時。SecondActivity就呈現出來了。而原來的MainActivity則被SecondActivity覆蓋掉而不再擁實用戶焦點。因此,可得出以下的3個結論。
ⅠMainActivity的onPause()方法被調用。
ⅡSecondActivity將會經歷與MainActivity一樣的顯示過程。
Ⅲ當完畢SecondActivity的展現後,MainActivity保存的回調接口(onSaveInstanceState())就被調用。接著還會調用MainActivity的onStop()方法。
⑤按BACK鍵返回到原來的Activity,看看會發生什麽?例如以下圖:
從上圖可知。發生了以下4件事情。
ⅠSecondActivity的onPause方法被調用。指示它即將被暫停。
Ⅱ因為MainActivity是以前被創建的Activity,因此這裏僅僅調用了它的onStart()以及onResume()方法來完畢Activity的又一次展現。
ⅢSecondActivity完畢了生命周期而被銷毀。
在這個過程中。它經歷了停止和銷毀兩個生命周期。這也就意味著當須要它又一次顯示的時候,僅僅能從又一次創建開始了。
Ⅳ假設此次再次按下BACK鍵,則MainActivity也將被銷毀。相同,它的onStop()以及onDestory()也會被依次調用。
深入剖析Android四大組件(一)——Activity生命周期具體解釋