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

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

Activityライフサイクルの管理(2) Activityの一時停止と再開

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



普通にアプリを使っていると、フォアグラウンドにあるActivityは時々Activityの一時停止(pause)を引き起こすような他のビジュアルコンポーネントによって遮られる。例えば、ダイアログのスタイルの内の1つのような半透明のActivityが開いたとき、以前のActivityは一時停止する。Activityがまだ一部でも見えているが、現在はフォーカスが当たっていない間は一時停止のままでいる。

しかし、一度Acitivityが完全に遮られて非表示になるとそれは停止(stop)する。

Activityが一時停止状態に入ると、システムはActivityのonPause()メソッドを呼び出すことで、例えばビデオのような一時停止中も続けるべきでない継続したActionを停止したり、またはユーザーがアプリを離れても維持したいような永続的に保存されるべきあらゆる情報の保持をすることを可能にする。ユーザーが一時停止状態からActivityに戻ると、システムはonResume()メソッドを呼んでActivityを再開する。

ActivityがonPause()を受けたとき、それはActivityが一時停止状態に入り、ユーザーがまたActivityにフォーカスを戻すかもしれないという指摘かもしれない。しかしそれは普通、ユーザーがActivityを離れようとしているということの最初の指摘である。

http://developer.android.com/images/training/basics/basic-lifecycle-paused.png
図1:半透明のActivityがあなたのActivityを遮るとき、システムはonPause()を呼びActivityはPaused(一時停止)状態(1)で待つ。ユーザーが一時停止状態からActivityに戻るとシステムはonResume()を呼び出す。

Activityの一時停止

システムがActivityのonPause()を呼ぶと、技術的にはActivityがまだ一部的に表示状態にあることを意味するが、それはほとんどの場合ユーザーがそのActivityを離れようとしていてすぐに停止(Stopped)状態に入る事を示唆している。通常はonPause()コールバックを以下のような事柄に使うべきである。

  • アニメーションの停止または他のCPUを消費する継続型アクション
  • 未保存の変更の保存。ただし、ここでの保存は書きかけのメールのような、ユーザーが永続的に変更を保持しておいてほしいと期待するようなものに限る。
  • ブロードキャストレシーバのようなシステムリソース、GPSのようなセンサーの制御、またはActivityの一時停止中でユーザーに必要とされないバッテリー寿命に影響のあるあらゆるリソースの解放。

例えば、アプリケーションがCameraを使う場合、onPause()メソッドはそれを解放するのに適した場所である。

@Override
public void onPause() {
    super.onPause();  // 常にスーパクラスは最初に呼ぶ。

    // 一時停止中には必要がないのでCameraの解放する。
    if (mCamera != null) {
        mCamera.release()
        mCamera = null;
    }
}

一般的には(フォームに入力された個人情報のような)ユーザーの変更を永続化領域に格納する為にonPause()を使うべきではない。ユーザーの変更を永続化領域に保持すべきなのはonPause()がユーザーが変更が(編集中のメールなど)自動保存されることを期待すると確信できる場合だけである。しかし、データベースへの書き込みのようなCPU負荷の高い処理は次のActivityへの画面遷移を送らせることからonPause()では避けるべきである(代わりに負荷の高い終了処理はonStop()中に実行するべきである)。

Activityが実際に停止しようとしている場合、ユーザーが次の場所に速やかに遷移できるようにonPause()メソッド内で実行する処理の量を相対的にシンプルに保つべきである。

Activityが一時停止すると、Activityのインスタンスはメモリ内に常駐しActivityを再開するときに呼び戻される。再開状態になるまでのコールバックメソッドのいずれかで生成されたコンポーネントも再初期化の必要はない。

Activityの再開

ユーザーがActivityを一時停止状態から再開するときシステムはonResume()メソッドを呼び出す。

Activityが最初に作られたときを含めて、それがフォアグラウンドにくるとシステムは毎回このメソッドを呼び出すことに注意すること。というわけで、onPause()で解放されたコンポーネントの初期化やActivityが再開(Resumed)状態になるたびに必ず初期化が必要にな処理を実行するためにonResume()を実装すべきである。(アニメーションの開始やフォーカスがある場合だけひつようなコンポーネントの初期化など)

以下の例はonResume()は上のonPause()の例に対応しているので、Activityの一時停止で解放されたカメラを初期化している。

@Override
public void onResume() {
    super.onResume();  // 常にスーパクラスは最初に呼ぶ。

    // Get the Camera instance as the activity achieves full user focus
    // Activityが完全なフォーカスを得たらCameraインスタンスを取得する
    if (mCamera == null) {
        initializeCamera(); // カメラを初期化するためのローカルメソッド
    }
}