前人未踏の領域へ Androidアプリ開発編

Androidアプリ開発に関する調査メモ置き場。古い記事にはアプリ以外も含まれます。

Activityライフサイクルの管理(4) Activityの再構築

※本記事はhttp://developer.android.com/training/basics/activity-lifecycle/recreating.htmlの直訳です。
サンプルコードもそちらからダウンロードしてご利用下さい。


ユーザーがバックボタンを押したとか、Activityが自身のfinish()を呼ぶなど、標準的なアプリの振る舞いに起因してActivityが破棄されるにはいくつかのシナリオがある。システムはまた現在停止状態にあり、長い時間使われていなかったか、フォアグラウンドのActivityがよりリソースを要求し、システムがメモリを確保するためにバックグラウンドプロセスを終了する必要がある場合にはActivityを破棄するかもしれない。

ユーザーがバックボタンを押したりActivityが自分自身をfinish()したためにActivityが破棄されると、Activityがもはや必要とされないことを示す振る舞いから、システムのActivityインスタンスは永遠に失われる。しかし、もしシステムがシステム制約上でそのActivityを破棄する場合、実際のActivityのインスタンスは失われるが、システムはユーザーがそこに戻って来たような場合にそれが存在していたことを覚えていて、システムはActivityが破棄されたときの状態を記述した保存データのセットを使って新たにActivityのインスタンスを作成する。前の状態を復元するためにシステムが使用する保存データは"instance state"と呼ばれ、Bundleオブジェクト内でkey-valueのペアでコレクションされる。

注意:画面を回転させると、Activityは毎回破棄され、再構築される。スクリーンの縦横を切り替えるとき、システムはスクリーン設定が変更され、Activityがレイアウトのような代替のリソースを読み込む必要があるかもしれないことから、フォアグラウンドのActivityを破棄し、再構築する。

デフォルトではシステムはActivityレイアウト内のそれぞれのViewオブジェクトについての(EditText内の文字列のような)情報を保存するためにBundleインスタンス状態を使用する。したがって、もしActivityのインスタンスが破棄され再構築されると、レイアウトの状態は自動的に元の状態に復元れさる。しかし、ActivityはActivity内のユーザーの進捗追跡のためのメンバー変数のような、復元するためにより多くの情報を持つかもしれない。

Activityのインスタンス状態を保存するための追加のデータを加えるために、これまでのレッスンにはなかったActivityのライフサイクルの追加のコールバックメソッドがある。そのメソッドはonSaveInstanceState()でシステムはユーザーがActivityを離れるときに呼び出す。システムがこのメソッドを呼ぶとき、Activityが予期せず破棄された場合に追加の情報を追加できるようBundleオブジェクトを渡す。システムがActivityのインスタンスが破棄されたあと、再構築が必要な場合、ActivityのonRestoreInstanceState()メソッドとonCreate()メソッドに対して同じBundleオブジェクトが渡される。


http://developer.android.com/images/training/basics/basic-lifecycle-savestate.png
画面2:システムがActivityを停止し始めると、それはonSaveInstanceState() (1) を呼ぶので、Activityのインスタンスを再構築する必要があるケースで保存しておきたい追加のデータを記述することができる。Activityが破棄され、同じインスタンスが再構築される必要がある場合、システムは(1)で定義されたデータをonCreate()メソッド(2)とonRestoreInstanceState()メソッド(3)の両方に渡す。

Activity状態の保存

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状態の復元

@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);
}