android Activity生命週期(設備旋轉、數據恢復等)與啓動模式

博客逐步遷移至 極客兔兔的小站html

1.Activity生命週期

    接下來將介紹 Android Activity(四大組件之一) 的生命週期, 包含運行、暫停和中止三種狀態,onCreate、onStart、onResume、onPause、onStop、onDestroy六種系統調用方法。java

1.1 Activity生命週期簡介與測試

生命週期

    如圖所示,Activity實例能夠在生命週期狀態發生關鍵性轉換時完成某些工做。android

  • onCreate() 建立,該方法是最常被覆蓋的方法,第一次建立實例時調用, 通常用來完成實例建立的初始化操做,包括實例化組件,設置監聽器,訪問外部模型數據等。
  • onStart() 開始,當Activity處於可見狀態的時候就會調用onStart方法,包括建立完實例顯示,或者從其餘活動切換到活動時調用。
  • onResume() 準備,當Activity得到用戶焦點時調用。
  • onPause 暫停,當Activity準備調用或者恢復另外一個活動時調用,失去焦點時,例如啓動一個Dialog調用。該方法能夠釋放一些消耗CPU的資源,保存一些關鍵數據,可是執行速度要快,不然影響新的棧頂活動使用。
  • onStop 中止,徹底不可見時調用。例如成功啓動了另一個活動,該活動離開棧頂不可見。啓動Dialog不會執行該方法。
  • onDestroy 銷燬,這個方法在活動銷燬時調用。
// 可使用如下方法進行測試。
public class MainActivity extends Activity {
    
    private String TAG = "MainActivity";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG,"Create");
    }
    
    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "Start");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "Resume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "Pause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "Stop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "Destroy");
    }
}

1.2 設備旋轉時的生命週期與數據恢復

設備旋轉

    使用上面的日誌打印測試方法發現, 設備旋轉時生命週期如圖所示,即設備旋轉時,當前活動實例會被系統銷燬,而後建立一個新的實例。ide

    由於旋轉設備會改變設備配置(device configuration),設備配置包括屏幕的方向、密度、尺寸、鍵盤類型、底座模式等,爲匹配不一樣的設備,可使用不一樣的佈局文件,這和Web開發中 針對不一樣寬度的屏幕選擇不一樣CSS樣式殊途同歸,如何建立不一樣佈局適配不一樣配置設備不在本文討論之列。佈局

    設備旋轉時,臨時數據會丟失。例如你使用了一個變量記錄了用戶點擊了多少次按鈕,設備旋轉以後,Activity從新建立,這個變量就被初始化了,這裏可使用Bundle對象來恢復。保存數據能夠覆蓋onSaveInstanceState()方法。測試

    例以下面的代碼,按3次按鈕,旋轉屏幕後,將打印出saved currentPage:3 init mCurrentPage:0,點擊次數存在了Bundle對象中,並在onCreate()中獲取到。3d

/*
 * onSaveInstanceState()一般在onPause、onStop、onDestroy前由系統調用
 * onCreate()傳入的參數savedInstanceState可獲取保存的變量
 */
public class MainActivity extends Activity {

    private static final String KEY = "currentPage";
    private static final String TAG = "MainActivity";
    private Integer mCurrentPage = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCurrentPage += 1;
            }
        });
        if(savedInstanceState != null){
            // 打印使用Bundle保存的currentPage信息
            Log.d(TAG,"saved currentPage: " + savedInstanceState.getInt(KEY,0));
            // 打印新建活動mCurrentPage的值,總爲0
            Log.d(TAG,"init mCurrentPage: " + mCurrentPage);
            // ... update code
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // 使用key-value對的方式存儲臨時變量
        outState.putInt(KEY, mCurrentPage);
    }
}

1.3 Activity暫存與Activity記錄

    當系統回收內存時,處於Pause、Stop狀態的Activity可能被銷燬,此時系統會調用onSaveInstanceState(),用戶數據被存儲在Bundle對象中,系統將Bundle對象放入Activity記錄,能夠將這種狀態理解爲Activity的暫存狀態(無實例有記錄)。日誌

    Activity暫存後,當前活動不復存在,Activity記錄可幫助用戶返回應用時活動的快速恢復,提供一個好的用戶體驗。可是當用戶按了後退鍵,系統會完全銷燬當前活動,Activity記錄同時被清除,系統重啓也會被清除該記錄。code

2.Activity啓動模式

2.1 standard(默認)

     standard是活動默認的啓動模式,Android是使用返回棧來管理活動的,所謂棧就是先進後出,後進先出。該模式下,每啓動一個新的活動,就會在返回棧中入棧,並處於棧頂的位置(即用戶當前見到的活動)。系統不會 檢查該活動的實例已經在返回棧中存在,每次啓動都新建一個。當前返回棧爲A->B(B爲棧頂),新建活動B, 返回棧變爲A->B->B。xml

2.2 singleTop

    standard模式有時並不合理,好比活動實例已經在棧頂了,再次啓動時還需再建立一個實例, 這會形成資源的浪費。singleTop模式下,若是當前棧頂已是該活動實例,則認爲能夠直接使用,而再也不建立新的活動。當前返回棧爲A->B(B爲棧頂),新建活動B, 返回棧仍爲A->B。

<!--AndroidManifest.xml-->
<!--設置方式,launchMode -->
<activity android:name=".MainActivity"
    android:launchMode="singleTop"
    android:label="AndroidDialog">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

2.3 singleTask

    singleTop模式能夠避免重複建立棧頂活動的問題,可是若是啓動活動不在棧頂,而以前已經建立過,仍是會重複建立。例如A->B->C,當前已有三個活動A、B、C,C位於棧頂,再建立B,返回棧變爲A->B->C->B(另外一個實例)。singleTask模式可讓返回棧中每一個活動只存在一個實例,若是發現當前須要啓動活動已經在棧中,則直接使用,可是該活動之上的全部活動所有出棧;如沒有發現,則建立新的實例。例如A->B->C,如此時建立活動B,則返回棧變爲A->B(B存在,使用B,C出棧);若此時建立活動D,則返回棧變爲A->B->C->D

2.4 singleInstance

    singleInstance模式是四種啓動模式中最複雜的,不一樣於上述三種模式,指定爲singleInstance模式的活動會啓動一個新的返回棧來管理這個活動。例如當前有活動A、B、C,活動A、C爲默認啓動模式,B指定爲singleInstance模式,首先新建A,A活動頁面啓動B,B啓動C,此時的返回棧並非A->B->C,而是存在2個返回棧,一個是A->C,另外一個是B。此時按下BACK鍵返回,將從C返回到A,再按一次,A返回到B,按第三次,程序退出。即返回時,先清空棧A->C,再清空棧B。     singleInstance模式有什麼應用場景呢?例如當前程序中某個活動容許其餘活動調用,若是想多個程序共享該活動的一個實例A,那麼每個程序都有一個返回棧,若使用前3種模式,該活動入棧時必然建立新的實例,沒法實現實例共享。singleInstance能很好地解決這個問題。

相關文章
相關標籤/搜索