android系統不像其他的編程應用一樣用main()方法開始,而是在activity中通過activity的各個生命周期回調方法來初始化代碼.
在Activity的生命周期中,系統調用一系列核心生命周期方法一步步走向一個金字塔頂端,Activity生命周期每一個回調都相當于朝向金字塔的一步,隨著系統創造一個activity示例,每個回調方法都使得activity走向金字塔頂端更近一步,金字塔頂端就是activity運行在前臺可以與用戶交互的狀態,隨著用戶離開Activity,系統調用其他的生命周期回調方法慢慢走下金字塔,某些情況下,activity會在下來一兩步后停下等待(比如當用戶切換到其他的app中),這種情況activity有可能回到金字塔頂端(如果用戶切回到當前activity),并且activity恢復到離開activity時的樣子
根據你自己的activity的復雜度,你可以不必需要重寫所有生命周期方法,但是你必須理解每一個生命周期回調方法的重要性以確保你的app的體驗和所期望的一致,重寫生命周期方法使得你的app用戶體驗更好,主要體現在以下幾個方面:
在接下來的學習中我們將知道,Activity在各種不同的狀態之間切換的時候有好幾種情形。然而,只有三種狀態是靜態的,也就是說,activity可以在這三個狀態可以長時間停留。
Resumed(恢復/運行狀態) 在這種狀態,activity在前臺并且可以和用戶交互(有時也稱作“運行”狀態)Paused(暫停狀態) 在這種狀態,activity是被另一個activity擋住一部分的,這擋住它的activity是半透明的或者沒有覆蓋整個屏幕,暫停的activity不能接收用戶的指令也不能執行任何代碼.Stopped(停止狀態) 在這種狀態,activity完全被隱藏,且對用戶是不可見的,它被認為是在后臺運行,當進入stopped狀態時,activity實例和所有的狀態信息比如成員變量都被保存起來了,但是它也不能執行任何代碼.其他的狀態(Created 和Started)都是很短暫的狀態,系統很快的通過調用生命周期的方法來從他們跳轉到下一個狀態,系統調用onCreate之后,會馬上調用onStart, 緊接著就是onResume了.以上就是基本的activity生命周期,現在我們將來學習特殊的生命周期行為了.
注意:在新建的android項目中默認有一個activity是app的入口activity. 如果你的所有的activity都是要么沒有Main action或者LAUNCHER category,或者兩者都沒有,那么你的app圖標將不會出現在在主屏app列表中.
大多數包含多個activity的app允許用戶表現不同的action,無論你的activity是程序的主入口(點擊app圖標進入的activity)還是回應用戶action打開的activity,系統將通過onCreate()方法創造這個activity的實例.
你必須重寫onCreate方法來執行基本的應用啟動邏輯,這只在activity的生命周期中執行一次,例如,你重寫onCreate方法應該定義用戶界面和實例化類范圍內的變量.
例如,接下來的onCreate()方法的實例向我們展示了執行基本的activity啟動的一些代碼,比如定義用戶界面(xml布局文件中定義的),定義成員變量,配置一部分UI.
TextView mTextView; // Member variable for text view in the layout@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Set the user interface layout for this Activity // The layout file is defined in the PRoject res/layout/main_activity.xml file setContentView(R.layout.main_activity); // Initialize member TextView so we can manipulate it later mTextView = (TextView) findViewById(R.id.text_message); // Make sure we're running on Honeycomb or higher to use ActionBar APIs if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // For the main activity, make sure the app icon in the action bar // does not behave as a button ActionBar actionBar = getActionBar(); actionBar.setHomeButtonEnabled(false); }}注意:使用SDK_INT來防止舊版本的系統執行新版本系統的代碼,這部分代碼在Android 2.0 (sdk = 5)及以上是好使的,舊版本系統執行這段代碼會出現runtime異常.

注意:系統只能在調用onPause()和onStop()后才會調用onDestory(),除非你在onCreate方法中調用了finish()方法,在某些情況下,比如你的activity決定啟動另一個activity ,你可能會在onCreate()方法中調用finish() 然后銷毀activity,在這種情況下,系統將會馬上調用onDestory()而不調用其他的生命周期方法.
在正常的app使用過程中,前臺activity有時會被另外的可視化組件阻塞,導致activity進入Paused狀態,例如,當一個半透明的activity打開的時候(比如dialog樣式的activity),先前的activity暫停了,只要這個activity是部分可視的但卻沒有獲取到焦點 它就是paused狀態.
然而,只要這個這個activity被完全的阻塞了并且不能被看見,它將進入stoped狀態(下節課中我們將討論).
由于你activity進入了paused狀態,系統調用你的activity中的onPause()方法,它允許你停止在暫停狀態下不該繼續的動作,或者保留一些應該被永久保留以防止用戶離開你的app的信息,這樣當你的用戶從paused狀態回來的時候,系統將恢復它并且調用onResume方法.
注意:當你的app收到要調用onPause方法時,這可能是表示你的activity將會進入onPause狀態一段時間并且用戶可能會某一時刻返回到你的activity,然而,這通常代表著用戶要離開你的activity了.
當系統調用你的activity的onPause()方法時,理論上意味著你的activity還是部分可見的,但大多數通常是表示用戶離開你的activity了,并且通常很快進入stopped狀態你應該嘗嘗使用onPause()回調來:
停止動畫或者其他正在繼續消耗CPU的行為.提交沒有保存的改變,只在用戶在離開的時候期望這些改變是永久保存的情況下執行(比如郵箱草稿).釋放系統資源,比如廣播接收器,傳感器(例如GPS)或者任意其他在activity是暫停狀態下且用戶不需要的影響電池壽命的資源文件.例如,如果你的應用使用了照相機,onPause()方法將是一個好的地方來釋放資源.
@Overridepublic void onPause() { super.onPause(); // Always call the superclass method first // Release the Camera because we don't need it when paused // and other activities might need to use it. if (mCamera != null) { mCamera.release() mCamera = null; }}一般來說,你不應該在onPause()中永久存儲這些改變(比如表單中的個人信息),只有當你很確信在onPause()中這些用戶期望做出的改變自動需要永久保存起來時(比如郵件草稿)你才能這么做. 然而,你應該盡量避免CPU在onPause()中高強度工作,比如寫入數據到數據庫,因為這將減慢activity跳轉到下一個activity的可視化的轉變(你應該把這些高強度的運算放在onStop()中執行).
你應該使得在onPause()中的計算相當簡單以使得如果你的activity要被stop的時候,用戶的跳轉到下一個activity的速度很快.
注意:當你的activity被暫停了, Activity實例確是一直存在于內存之中,并且當activity回復的時候會被再次調用. 你不需要再次實例化已經在曾走向Resumed狀態被調用的生命周期的方法中被創建的組件.
當用戶從Paused狀態恢復時,系統將調用onResume()方法.
我們注意到系統在每次進入前臺用戶視野的時候都會掉用這個方法,包括首次創建的時候,這樣我們應該重寫onResume()來初始化在onPause()中被釋放的組件并執行任何其他的必須activity進入Resumed狀態需要初始化的變量的初始化(比如,開始動畫和只在activity獲取到用戶焦點時候初始化的組件).
下面onResume()的例子 上面onPause() 例子的相對方法,所以它初始化了在activity進入暫停狀態下釋放的照相機資源 .
@Overridepublic void onResume() { super.onResume(); // Always call the superclass method first // Get the Camera instance as the activity achieves full user focus if (mCamera == null) { initializeCamera(); // Local method to handle camera init }}合適的停止和重新開始activity一個在activity生命周期中重要的過程,它確保了你的用戶知道你的app一直是活著的么而且沒有丟失他們的進度,有這樣幾個關鍵的場景(activity停止并重新開始):
用戶打開了最近使用的app窗口并且從你的app切換到另一個app,你的app中的activity目前就處于前臺并且是停止狀態. 如果用戶從主屏圖標或者最近使用的app列表中回到你的app,那么這個activity將會restart.用戶在你的app中打開了一個新的activity,則當前的activity會在第二個activity創建的時候停止. 如果用戶在第二個activity頁面按了返回按鈕,澤第一個activity會restart.Antivity提供了2個生命周期方法,onStop() 和 onRestart(),這兩個方法允許你具體的處理你的activity在變為stopped和restarted狀態的過程. 不像表示部分UI被擋住的paused狀態,stopped狀態保證了UI不再是可視的并且用戶耳朵焦點已經在另一個activity上(或者別的app上).
注意:因為系統在activity處于stopped狀態時保持我們的Activity實例在內存中,所以很可能你不需要重寫onStop()和onRestart()方法(甚至是onStart()方法也不需要重寫),對大多數activity來說 他們都是相對比較簡單的,activity將會stop并restart剛剛好,你也許只需要使用onPause()來暫停正在執行的動作和與系統資源斷開連接。
當你的activity收到onStop()的回調方法,它就不再是可視的了,并且它應該釋放在用戶不再使用的時候不再需要的絕大多數資源,一旦你的activity停止了系統也許會在恢復系統內存的時候會銷毀實例,在極端情況下,系統也許會簡單的殺死你的app進程而不調用你的activity的onDestory()方法 ,素以使用onStop()來釋放資源是防止內存泄漏的重要的手段.
盡管onPause() 方法在onStop()之前調用, 你還是應該使用onStop()來執行更大的更密集型的cpu運算 ,比如把信息寫入數據庫.
例如,這里重寫了onStop()方法保存了便條草稿的內容能夠到本地的存儲:
@Overrideprotected void onStop() { super.onStop(); // Always call the superclass method first // Save the note's current draft, because the activity is stopping // and we want to be sure the current note progress isn't lost. ContentValues values = new ContentValues(); values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText()); values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle()); getContentResolver().update( mUri, // The URI for the note to update. values, // The map of column names and new values to apply to them. null, // No SELECT criteria are used. null // No WHERE columns are used. );}當你的activity進入了stopped狀態,activity對象仍然在內存中,他將會在activity恢復的時候被調用,你不需要再次初始化已經初始化過了的組件,系統也一直追蹤布局文件中每個View上午當前的狀態,所有如果用戶在EditText組件中輸入了一段文本,這些內容會被記錄起來,所以你不必擔心有沒有必要去保存或者修復它.
注意:即便當activity處于stopped狀態,系統銷毀了activity,它仍然保持著View對象的狀態(比如EditText中的文本),并把它存儲到Bundle(鍵值對)中,并且在用戶打開相同的實例的時候恢復他們(下一節我們講關于使用Bundle保存數據以防activity被銷毀或重建).
當我們的actvity從stopped狀態來到前臺,它收到了onRestart()方法的回調,系統同時會調用onStart() 方法,onStart()方法在每次activity變成可視狀態都會調用,要么在onRestart()之后執行,要么在onCreat()之后執行,然而onRestart() 方法,只有當activity從stopped狀態恢復時會被調用,所以你能使用它來執行特殊的復原工作,這也許是必須的工作僅當activity先前已經被停止了但還沒有被銷毀的時候.
app需要使用onRestart()來存儲activity狀態這件事是不尋常的,所有對這個方法應用到一般的app沒有任何的準則,然而因為你的onStop() 方法應該基本清除所有你的activity的資源,你將需要在acticity重新開始的時候重新實例化他們,不得不說的還有,你也需要在首次創建activity(內存中沒有activity的實例)的時候實例化他們. 因為這個原因, 你應該經常使用onStart() 回調方法作為onStop()方法的對應方法, 因為系統在創建activity和restart activity的時候都會調用onStart()方法.
例如,因為用戶在回到我們activity的時候可能已經離開我們的app很長一段時間了,onStart() 方法是一個好地方來驗證需要的系統特性是不是能用.
@Overrideprotected void onStart() { super.onStart(); // Always call the superclass method first // The activity is either being restarted or started for the first time // so this is where we should make sure that GPS is enabled LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); if (!gpsEnabled) { // Create a dialog here that requests the user to enable GPS, and use an intent // with the android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS action // to take the user to the Settings screen to enable GPS when they click "OK" }}@Overrideprotected void onRestart() { super.onRestart(); // Always call the superclass method first // Activity being restarted from stopped state }當系統銷毀了你的activity,它調用你的activity的onDestory方法。 因為一般來說你本應該在onStop()中釋放完了大多數資源, 但如果同時收到了調用onDestroy()的命令, 這種情況一般不多見,這個方法是你最后的機會來清除資源以防止內存泄漏,所以你應該確認額外的線程已經被銷毀并且像追蹤類的長時間運行的行為也被停止了.
有許多你的activity因為正常的app行為被銷毀的場景,例如當用戶按下了返回按鈕或者你的activity通過調用finish()發信號銷毀自己, 系統也有可能會在activity處于stopped狀態并且很長一段時間沒有被使用的時候銷毀activity,或者前臺activity需要更多的資源所以系統不得不關閉后臺進程來恢復內存.
當你的activity因為用戶按下返回按鈕被銷毀或者activity自己關閉自己,在系統看來因為這些行為導致的activity實例永遠消失了,這代表著activity不再被需要了,然而,如果系統銷毀因為系統約束銷毀了activity(而不是正常的app行為),則盡管真實的activity實例確實消失了,系統記得它存在過,這使得如果用戶再返回這個activity,系統會使用保存好的數據(activity被銷毀時保存的)創建一個新的activity的實例. 這些系統把他們用來復原先前的狀態的數據也被稱為“實例化狀態”,它是存儲在Bundle對象中的鍵值對.
注意:你的activity將會在你旋轉屏幕的時候被銷毀然后重建,當你的屏幕改變了方向。系統將會銷毀并重建前臺activity因為屏幕特征已經改變了而且你的activity也許需要去加載對應的與原來不一樣的資源(比如說layout布局).
默認地,系統使用Bundle實例化狀態來保存你的activity布局中的View對象的信息(比如EditText對象中的text文本值),所以如果你的activity實例被銷毀并且重建,布局的狀態被自動恢復到它先前的狀態,然而,你的activity也許有更多的你想恢復的狀態信息,比如activity中追蹤用戶進度的成員變量.
注意:為了使android系統恢復你的activity中所有view的狀態,每個view必須擁有一個唯一的ID,用 android:id 這個屬性來設置.
為了保存activity狀態額更多的數據,你必須重寫onSaveInstanceState() 回調方法. 系統在用戶離開你的activity的時候調用這個方法,并把這些數據傳遞給Bundle對象,這樣他們就會在activity意外被銷毀的時候被保存起來,如果系統一定要在自之后重建activity實例,它會回傳相同的Bundle 對象到onRestoreInstanceState() 和onCreate() 方法中.
隨著你的activity開始進入stopped狀態,系統調用onSaveInstanceState() 方法,所以你的activity能用鍵值對的方法保存狀態信息. 這個方法的默認的重寫保存了關于activity的View 分層信息,比如EditText中的文本信息或者ListView滾動到的位置.
為保存你的activity的更多狀態信息,你必須重寫onSaveInstanceState() 并增加鍵值對到Bundle對象. 例如:
static final String STATE_SCORE = "playerScore";static final String STATE_LEVEL = "playerLevel";...@Overridepublic void onSaveInstanceState(Bundle savedInstanceState) { // Save the user's current game state savedInstanceState.putInt(STATE_SCORE, mCurrentScore); savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel); // Always call the superclass so it can save the view hierarchy state super.onSaveInstanceState(savedInstanceState);}注意: 一定要調用父類的onSaveInstanceState() ,這樣默認的view分層信息狀態才會保存到Bundle對象中.
當你的activity先前被摧毀后被重建,你可以從系統傳給你的Bundle中恢復你保存的狀態, onCreate() 和onRestoreInstanceState() 回調方法會收到相同的包含相同狀態信息的Bundle對象.
因為onCreate() 方法在創造一個新的activity實例或者重建先前的activity中被調用. 你必須在嘗試從中取值的之前檢查是否這個狀態Bundle是不是空的,如果是空的,則系統正在創建一個新的實例,反之則是在恢復先前被銷毀的activity實例.
例如:下面是你在onCreate()中取狀態數據的實例
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Always call the superclass first // Check whether we're recreating a previously destroyed instance if (savedInstanceState != null) { // Restore value of members from saved state mCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); } else { // Probably initialize members with default values for a new instance } ...}如果不在onCreate()方法中恢復,你也可以選擇重寫 onRestoreInstanceState(),這個方法將在系統調用完onStart()方法后調用,只有當至少一個保存的狀態要恢復時系統才會調用onRestoreInstanceState(),所以你不需要檢查Bundle是不是空的:
public void onRestoreInstanceState(Bundle savedInstanceState) { // Always call the superclass so it can restore the view hierarchy super.onRestoreInstanceState(savedInstanceState); // Restore state members from saved instance mCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);}注意: 一定要調用父類的 onRestoreInstanceState()才能恢復View分層狀態信息.
新聞熱點
疑難解答