Android開發之Activity的生命周期

 

可能很多人會感覺Activity很簡單,但是經歷瞭半年的android開發,我發現我對Activity的的理解還是比較淺顯的,其實Activity並沒有我們想象的那麼簡單今天花瞭一個下午學習瞭Activity的生命周期,為以後忘記後迅速回顧,做準備。

一、首先看下官網給出activity的生命周期圖


我們可以從圖中分析它的執行過程:
1.啟動Activity:系統會首先調用onCreate方法,然後調用onStart方法,最後調用onResume()方法。此時Activity進入運行狀態
2.當前Activity被其他Activity覆蓋或處於鎖屏狀態:系統會調用onPause方法,然後調用onStop方法,此時Activity處於停滯狀態。
3.當前Activity由覆蓋狀態回到前臺或解鎖屏:系統會調用onRestart方法,然後調用onStart方法,最後調用onResume方法,再次進入運行狀態。
4.當前Activity跳轉到新的Activity界面或Home鍵回到主屏,退到後臺:系統會先調用onPause方法,然後調用onStop方法進入停滯狀態
5.用戶後退回到此Activity:系統會先調用onRestart()方法,然後調用onStart方法,最後調用onResume方法,再次進入運行狀態
6.當前Activity處於被覆蓋狀態或者後臺不可見狀態,即第二和第四步,系統內存不足,殺死當前Activity,而後用戶退回當前Activity:再次調用onCreate方法、onStart方法、onResume方法,進入運行狀態。 7.用戶退出當前Activity:系統會調用onPause方法,然後調用onStop方法最後調用onDestroy方法,結束當前Activity 以上的Activity方法的生命周期是很簡單的,但是任何簡單的東西,隻有我們通過實例驗證才能理解的更加透徹,記憶更加深刻, 二、實例分析

 

實例代碼:

 

package com.example.activitypractice;

import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {

     private static final String TAG = MainActivity;
     
     private Button btn_jump;
     private String saveData= 存放的數據 ;

     //Activity創建時調用
     @Override
     protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
           setContentView(R.layout. activity_main);
           
            btn_jump=(Button) findViewById(R.id. btn_jump);
            btn_jump.setOnClickListener( new OnClickListener() {
                
                 public void onClick(View v) {
                     Intent intent= new Intent(MainActivity.this,JumpToActivity.class );
                     startActivity(intent);
                }
           });
           
           Log. i(TAG,執行瞭onCreate方法 );
     }
     
     //Activity創建或者從後臺重新回到前臺時被調用
     @Override
     protected void onStart() {
            super.onStart();
           Log. i(TAG,執行瞭onStart方法 );
     }
     
     //Activity從後臺重新回到前臺時被調用
     @Override
     protected void onRestart() {
            super.onRestart();
           Log. i(TAG,執行瞭onRestart方法 );
     }
     
     //Activity創建或者從被覆蓋、後臺重新回到前臺時被調用
     @Override
     protected void onResume() {
            super.onResume();
           Log. i(TAG,執行瞭onResume方法 );
     }
     
     //Activity被覆蓋到下面或者鎖屏時被調用 
     @Override
     protected void onPause() {
            super.onPause();
           Log. i(TAG,執行瞭onPause方法 );
     }
     
     //退出當前Activity或者跳轉到新Activity時被調用 
     @Override
     protected void onStop() {
            super.onStop();
           Log. i(TAG,執行瞭onStop方法 );
     }
     
     //退出當前Activity時被調用,調用之後Activity就結束瞭 
     @Override
     protected void onDestroy() {
            super.onDestroy();
           Log. i(TAG,執行瞭onDestroy方法 );
     }

     //Activity窗口獲得或失去焦點時被調用,在onResume之後或onPause之後 
   /* @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        Log.i(TAG, onWindowFocusChanged called.);
    }  */
     
     /**
     * Activity被系統殺死時被調用.
     * 例如:屏幕方向改變時,Activity被銷毀再重建;當前Activity處於後臺,系統資源緊張將其殺死.
     * 另外,當跳轉到其他Activity或者按Home鍵回到主屏時該方法也會被調用,系統是為瞭保存當前View組件的狀態.
     * 在onPause之前被調用.
     */
     @Override
     protected void onSaveInstanceState(Bundle outState) {
           outState.putString( key, saveData);
           Log. i(TAG, onSaveInstanceState called.put saveData:  + saveData );
            super.onSaveInstanceState(outState);
     }
     
     /**
     * Activity被系統殺死後再重建時被調用.
     * 例如:屏幕方向改變時,Activity被銷毀再重建;當前Activity處於後臺,系統資源緊張將其殺死,用戶又啟動該Activity.
     * 這兩種情況下onRestoreInstanceState都會被調用,在onStart之後.
     */ 
     @Override
     protected void onRestoreInstanceState(Bundle savedInstanceState) {
           String getData = savedInstanceState.getString( key);
           Log. i(TAG, onRestoreInstacedState called.getData: +getData);
            super.onRestoreInstanceState(savedInstanceState);
           
     }   
}

 

在上面的例子中我們可以看到還有三個不是特別常見的方法,onWindowFocusChanged、onSaveInstanceState、onRestoreInstanceState方法這三個方法我們用的比較少下面也來說說它們的用法: (1)onWindowFocusChanaged方法 在Activity窗口獲得或失去焦點時調用,例如創建時首次展示在用戶面前、當Activity被其它Activity所覆蓋、Activity退到後臺、用戶退出當前Activity,這幾種條件都會調用onWindowFocusChanaged,並且當Activity被創建時是在onResume之後被調用,當Activity被覆蓋或者退到後臺或當前Activity退出時它是在onPause之後被調用的,如下圖Activity啟動之後被其它的activity覆蓋(點擊我們的跳轉按鈕)打印的日志
這個方法在很多場合下還是很有用的,例如程序啟動時想要獲取組件的尺寸大小,在onCreate中是無法取到的因為Window對象還沒有創建完,這時候我們就需要在onWindwosFocusChanaged裡獲取,這也是我們常用的方法。

 

 

(2)onSaveInstanceState: 1.在Activity被覆蓋或者退到後臺之後,系統資源不足,將其殺死,此方法會被調用; 2.在用戶改變屏幕方向時此方法會被調用; 3.在當前Activity跳轉到其他Activity或者按Home鍵回到主屏,自身退到後臺時,此方法會被調用。 第一種情況我們無法保證什麼時候發生,系統根據資源的緊張程度去調度;第二種是屏幕翻轉方向時,系統先銷毀當前Activity,然後再重建一個新的,調用此方法時,我們可以保存一些臨時數據,例如:當豎屏時加載一個進度條,切換到橫屏時如果不保存當前加載到多少橫屏時會重0開始,保存後就可以繼續加載,第三種情況系統調用此方法是為瞭保存當前窗口各個View組件的狀態。onSaveInstanceState的調用順序是在onPause之後,如下圖是在跳轉到其它的Activity所執行的方法
我們從圖中可以看出onSaveInstanceState方法是在onPause方法中執行的 (3)onRestoreInstanceState 1.在Activity被覆蓋或是退居後臺之後,系統資源不足將其殺死,然後又回到瞭此Activity,此方法會被調用 2.在用戶改變屏幕方向時,重建的過程中,此方法會被調用。我們可以重寫此方法,以便恢復一些臨時數據。onRestoreInstanceState的調用順序是在onStart方法之後。
之後我們來結合上面的例子來一 一看看Activity的生命周期在各種的情況下的變化
1.啟動Activity:
啟動Activity:系統會首先調用onCreate方法,然後調用onStart方法,最後調用onResume()方法。此時Activity進入運行狀態
2.在1跳轉到其他的Activity,或按Home鍵
系統會先調用onPause方法,然後調用 onSaveInstanceState方法,然後調用onStop方法進入停滯狀態
3.從後臺回到前臺

系統會先調用onRestart方法,然後調用onStart方法,然後調用onResume方法
4.修改在AndroidMainfest.xml中的配置,將android:theme屬性設置為@android:style/Theme.Dialog,然後再點擊跳轉按鈕,然後JumpToActivity覆蓋到LifeCycleActivity之上瞭,
此時調用的方法為:onPause和onSaveInstanceState,我們註意到,此時MainActivity的onPause方法被調用,並沒有執行onStop方法,因為此時的MainActivity沒有退居到後臺隻是被覆蓋或被鎖屏;onSaveInstanceState會在onPause之後被調用
5.在4的基礎上按回退鍵MainActivity從被覆蓋回到前面
此時執行onResume方法
6.退出
系統調用onPause、onStop、onDestroy方法。
不知道大傢有沒有發現在上面的所有的日志中並沒有執行onRestoreInstanceState方法,為什麼沒有執行它呢沒有滿足它執行的條件,從上面onRestoreInstanceState執行的條件我們發現第一種是不可預測的,但是第二種(即改變屏幕方向)的話我們可以模擬的
三、Activity屏幕方向的知識
我們可以為一個Activity指定一個特定的方向,指定之後即使轉動屏幕方向,顯示方向也不會跟著轉動
1.指定為豎屏:在AndroidManifest.xml文件中對指定的Activity設置android:screenOrientation:=portrait, 或者在onCreate方法中指定代碼為:
setRequestOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);就指定為瞭豎屏
2.指定為橫屏:在AndroidManifest.xml文件中對指定的Activity設置android:screenOrientation:=landscape, 或者在onCreate方法中指定代碼為:
setRequestOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);就指定為瞭豎屏
在開發應用的過程中,為應用中的Activity設置特定的方向是經常用到的方法,可以為我們省去很多麻煩,但是我為瞭讓onRestoreInstanceState方法執行采用的是不固定屏幕的顯示方向我們對上面的代碼稍作修改加上onConfigurationChanged方法 現在源碼如下:

package com.example.activitypractice;

import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {

     private static final String TAG = MainActivity;
     
     private Button btn_jump;
     private String saveData= 存放的數據 ;

     //Activity創建時調用
     @Override
     protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
           setContentView(R.layout. activity_main);
           
            btn_jump=(Button) findViewById(R.id. btn_jump);
            btn_jump.setOnClickListener( new OnClickListener() {
                
                 public void onClick(View v) {
                     Intent intent= new Intent(MainActivity.this,JumpToActivity.class );
                     startActivity(intent);
                }
           });
           
           Log. i(TAG,執行瞭onCreate方法 );
     }
     
     //Activity創建或者從後臺重新回到前臺時被調用
     @Override
     protected void onStart() {
            super.onStart();
           Log. i(TAG,執行瞭onStart方法 );
     }
     
     //Activity從後臺重新回到前臺時被調用
     @Override
     protected void onRestart() {
            super.onRestart();
           Log. i(TAG,執行瞭onRestart方法 );
     }
     
     //Activity創建或者從被覆蓋、後臺重新回到前臺時被調用
     @Override
     protected void onResume() {
            super.onResume();
           Log. i(TAG,執行瞭onResume方法 );
     }
     
     //Activity被覆蓋到下面或者鎖屏時被調用 
     @Override
     protected void onPause() {
            super.onPause();
           Log. i(TAG,執行瞭onPause方法 );
     }
     
     //退出當前Activity或者跳轉到新Activity時被調用 
     @Override
     protected void onStop() {
            super.onStop();
           Log. i(TAG,執行瞭onStop方法 );
     }
     
     //退出當前Activity時被調用,調用之後Activity就結束瞭 
     @Override
     protected void onDestroy() {
            super.onDestroy();
           Log. i(TAG,執行瞭onDestroy方法 );
     }

     /**
     * Activity被系統殺死時被調用.
     * 例如:屏幕方向改變時,Activity被銷毀再重建;當前Activity處於後臺,系統資源緊張將其殺死.
     * 另外,當跳轉到其他Activity或者按Home鍵回到主屏時該方法也會被調用,系統是為瞭保存當前View組件的狀態.
     * 在onPause之前被調用.
     */
     @Override
     protected void onSaveInstanceState(Bundle outState) {
           outState.putString( key, saveData);
           Log. i(TAG, onSaveInstanceState called.put saveData:  + saveData );
            super.onSaveInstanceState(outState);
     }
     
     /**
     * Activity被系統殺死後再重建時被調用.
     * 例如:屏幕方向改變時,Activity被銷毀再重建;當前Activity處於後臺,系統資源緊張將其殺死,用戶又啟動該Activity.
     * 這兩種情況下onRestoreInstanceState都會被調用,在onStart之後.
     */ 
     @Override
     protected void onRestoreInstanceState(Bundle savedInstanceState) {
           String getData = savedInstanceState.getString( key);
           Log. i(TAG, onRestoreInstacedState called.getData: +getData);
            super.onRestoreInstanceState(savedInstanceState);
           
     }
     
     //當指定瞭android:configChanges=orientation後,方向改變時onConfigurationChanged被調用,並且activity不再銷毀重建
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            switch (newConfig. orientation) {
            case Configuration. ORIENTATION_PORTRAIT://豎屏
                Log. i(TAG,豎屏 );
                setContentView(R.layout. portrait);
                 break;
            case Configuration. ORIENTATION_LANDSCAPE://橫屏
                Log. i(TAG,橫屏 );
                setContentView(R.layout. landscap);
            default:
                 break;
           }
     }    
}

需要註意的是我們必須在手機上設置(註意:要在設置中設置自動旋轉屏幕我用的三星的測試機是在設定–>我的設備–>顯示 在顯示裡有自動旋轉屏幕選項)自動旋轉屏幕才可以 然後當我們旋轉屏幕時,我們會看到Activity首先會銷毀然後重建,系統會調用onSaveInstanceState方法並在Bundle對象中保存瞭一個臨時的數據,當Activity銷毀後再重建時調用onRestoreInstancedState方法我們從中可以把保存的數據取出來日志如下:

但是Activity銷毀後再重建,這有時候並不是我們想要的,那麼我們應該怎樣避免這種情況呢?這是我們應該在清單文件中對應的Activity中配置android:configChanges=orientation然後我們再旋轉屏幕
每次在旋轉的時候都調用瞭onConfigurationChanged方法,並且Activity沒有瞭銷毀重建的過程 在上面的配置過程中我們需要註意幾點: 1.如果在Activity中配置瞭android:screenOrientation屬性,則會使android:configChanges=orientation失效。 2.在配置android:configChanges時需要註意:如果是Android 4.0,則是orientation|keyboardHidden|screenSize,如果是 4.0之前的版本android:configChanges=orientation|keyboardHidden 關於android:configChanges配置時需註意的事項見此鏈接

 

 

 

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *