Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 跟著Google學Android —— 3.1 管好Activity的生命周期

跟著Google學Android —— 3.1 管好Activity的生命周期

編輯:關於Android編程

當我們在app的不同頁面間穿梭翱翔的時候,app中的Activity也在他們各自的生命周期中轉換著不同的狀態。當用戶執行進入或者是離開某個Activity的操作時,Android系統會調用一系列生命周期的回調函數進行處理,而我們也可以重寫這些回調函數,讓Activity在不同的狀態下執行我們想要的操作。

生命周期回調方法

下圖展示了一個Activity的生命周期以及回調方法。這張圖看起來就像是一個梯形金字塔,每一步都對應著Activity的一種生命狀態。

\

在這些狀態中,只有如下三種狀態是靜態的,即可持續一段時間的,其他狀態都是瞬態的:

Resumed:在這個狀態下,Activity處於前台,用戶可以與它交互(也可以稱之為Running態,即運行態);

Paused:在這個狀態下,Activity部分被其他Activity遮擋(其他處於前台的Activity是半透明的或者並沒與充滿整個屏幕),處在這個狀態的Activity並不接收用戶輸入,也不執行任何代碼;

Stopped:在這個狀態下,Activity是完全被隱藏的,用戶無法看到,這種狀態可以認為Activity處於後台,這個Activity實例以及它的狀態信息在這種狀態下都被保存了下來,但是不能執行任何代碼。

Created和Started這兩個狀態都是瞬間態的,系統會在到達這兩個狀態後很快就調用後面的生命周期回調方法,即系統在調用onCreate()之後緊跟著就會調用onStart(),然後再緊跟著調用onResume()。

Cteate Activity

當用戶點擊app圖標後,系統會調用你聲明為launcher(或是main)Activity對應的onCreate()方法。這個Activity也是你的app的UI主入口。這也是Android系統和其他編程模式不同的地方,它並不是通過調用main()函數來啟動,而是在不同的生命周期狀態時調用不同的生命周期回調方法。 我們可以在AndroidManifest.xml文件中通過intent-filter定義哪個Activity將作為launcher(一般在我們創建項目的時候Android Studio已經幫我們完成了這步):

    
        
        
    
需要注意的是,如果MAIN或者是LAUNCHER二者之一沒有定義,則這個app的圖標將不會顯示在安卓系統中。   無論用戶是在安卓系統中點擊app圖標開啟一個Activity還是在app內部翱翔時跳轉到新的Activity,系統都會通過調用onCreate()方法來創建對應的Activity實例。 onCreate()在一個Activity的生命周期中僅會調用一次,所以我們可以在這個方法中實現一些UI和成員變量的初始化動作,例如:
TextView mTextView; // Member variable for text view in the layout

@Override
public 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);
    }
}
技術上來說,在調用onStart()的時候Activity對用戶就是可見的了。   總結下,創建Activity的三部曲:onCreate() -> onStart() -> onResume()。
\

Pause & Resume Activity

只要某個Activity是部分可見的,且並不處於焦點,則這個Activity就保持在Paused態。一旦完全不可見,則變為了stopped態。如果用戶從Paused態回到這個Activity,則系統會調用onResume()方法,具體循環如下圖: \ 雖然系統調用onPause()方法是因為你的Activity被部分遮擋,但更普遍的其實是用戶就要離開你的app了,所以我們應該在這個狀態下做些事情: 1) 停止動畫或者是其他在執行的可能會消耗CPU的動作; 2) 提交未保存的修改,這個動作僅當可以確認用戶希望這些數據在他們離開app後也可以得到的保存的時候(例如短信草稿); 3) 釋放系統資源,例如broadcast receivers、對傳感器(例如GPS)的操作以及其他可能在Paused時候消耗電量而用戶又不需要的資源。 舉個例子:
@Override
public 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()中我們應該盡量做些簡單的操作,而避免做高CPU負荷的操作,例如寫入數據庫,因為這會減慢跳轉到下一個Activity的速度(大負荷的操作我們可以在onStop()中執行)。 在Paused的時候,Activity的實例還是存儲在內存中的,所以我們並不需要重新初始化各個部件。   當用戶從Paused態恢復Activity的時候,系統就會調用onResume()。需要注意的是,每次Activity來到前台的時候系統都會調用這個方法,即使是app第一次啟動。正是由於這樣,我們需要在這個方法中實現對onPause()中釋放的組件的重新初始化,以及對那些每次到達Resumed態都要發生的事件進行處理,舉個例子:
@Override
public 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
    }
}

Stop & Restart Activity

有幾個關於stop和restart的關鍵場景: 1) 用戶打開“最近使用的程序”窗口,從你的app跳轉到另一個app,則你的app中目前在前台的Activity變為stopped態,如果用戶通過點擊你的app圖標或者是“最近使用的程序”窗口再導航回你的app,則Activity會重新開始(restart); 2) 當用戶在你的app中導航跳轉到一個新的Activity時,當新的Activity被創建後當前的Activity就停止了,如果用戶點擊“返回”按鈕,則這個Activity會重新開始; 3) 用戶在使用app的時候在同一台手機上接到了一通電話。 從進入stop到restart再到resume的流程如下: \ 當Activity在stop之後,系統可能由於需要恢復系統內存而destroy Activity實例,極端情況下也可能不調用onDestroy()就直接將app的進程結束了。所以我們有必要在onStop()就釋放可能漏內存的資源。 雖然我們在onPause()和onStop()中都會執行一些清理工作,但前面也提到了,onPause()中應盡量做一些簡單的工作,而onStop()中可以做一些高負荷的工作。 舉個例子:
@Override
protected 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實例會保存在內存中,所以在恢復的時候我們並不需要重新初始化。同時,系統也記錄了布局中各個view的當前狀態,所以如果用戶在文本輸入框中輸入了文字,那麼這些內容會被保存下來,所以並不需要我們去另外存儲及還原它們。
  onRestart()僅在Activity從stopped變為resumed態時會被調用,而onStart()在每次Activity變得可見的時候都會被調用(無論是restart的還是第一次創建),所以可以在onRestart()中執行一些特殊的恢復操作,僅在Activity之前是stopped,而不是destroyed的時候需要。 由於在onStop()的時候基本上清掉了所有資源,所以用onStart()來與onStop()作為配對是更好的,舉個例子,當我們離開應用程序很久了之後,onStart()是一個很好的來驗證app所需要的系統特性已經開啟的地方:
@Override
protected 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"
    }
}

@Override
protected void onRestart() {
    super.onRestart();  // Always call the superclass method first
    
    // Activity being restarted from stopped state    
}

Recreate Activity

當Activity是由於用戶自己點擊返回或者是Activity自己調用finish()而銷毀的時候系統認為這個Activity實例永遠地消失了,因為這些操作表明沒有人再需要這個Activity了。但如果Activity是由於系統資源的限制被銷毀的,那麼系統會記住它的存在,當用戶再回來的時候,系統會使用在銷毀它的時候保存的數據來創建Activity實例。系統用來還原之前狀態所用的保存數據叫做“Instance state”,是存儲在Bundle對象中的鍵值對集合。 注意:每次當用戶旋轉屏幕的時候Activity都會被銷毀並重建,因為旋轉屏幕後屏幕的配置會改變,Activity有可能要加載其他的資源(如布局等)。 系統默認使用Bundle instance state來記錄Activity布局中的每個view的信息,所以如果我們要保存額外的Activity信息,我們則需要重寫onSaveInstanceState()這個回調方法,給Bundle對象添加鍵值對: \
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
//...

@Override
public 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);
}
當Activity要重建的時候,系統會將之前這個Bundle傳到onCreate()和onRestoreInstanceState()這兩個方法中。這兩個方法的差別在於,onCreate()中並不會檢查Bundle是否為null,而onRestoreInstanceState()僅當Bundle中有需要被還原的狀態時才會被調用,所以並不需要檢查是否為null,且這個方法是在onStart()後調用的。 兩種方法還原數據舉例:
@Override
protected 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
    }
    //...
}
 
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);
}

Destroy Activity

onDestroy()是Activity生命周期的最後一個回調函數,這意味著Activity的生命已經走到了盡頭。在這個方法中我們可以做一些清理工作,但其實大多數在onPause()和onStop()中都已經做掉了。需要注意的就是如果有service這種在後台跑的資源,可能會消耗CPU,所以在這裡都要終結掉。 一般情況下系統會在onPause()和onStop()之後調用onDestroy(),但有一種例外:當你在onCreate()方法中調用finish(),這種情況下系統立即直接調用onDestroy(),不會經過onPause()和onStop()這種。 代碼舉例:
@Override
public void onDestroy() {
    super.onDestroy();  // Always call the superclass
    
    // Stop method tracing that the activity started during onCreate()
    android.os.Debug.stopMethodTracing();
}
  谷歌官方的demo
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved