読者です 読者をやめる 読者になる 読者になる

woshidan's blog

そんなことよりコードにダイブ。

Activityの各ライフサイクルメソッドの役割について

Android lifecycle

Activityのライフサイクルメソッドをなんとなくしか理解していなかったので、

  1. onCreate
  2. onStart
  3. onResume
  4. onPause
  5. onStop
  6. onDestroy

の順番に呼ばれて、なんとなく、

  • onCreate、あるいはそこから呼び出すメソッドでレイアウトファイルに書いたViewの初期化を行い、onDestroyで削除。
  • onStartでBroadcastRecevierを登録し、onStopでBroascastRecevierの登録を解除
  • アニメーションのためのリスナーなどはonResume/onPauseで登録/解除する

というようにコードを書いていたのですが、正直、サンプルがこうだったからこう書いている、という部分が大きくて自信がなくなってきたので、あらためてまとめてみます。

ライフサイクルメソッドの役割について

Androidプログラミングレシピ増補改訂版 アーキテクチャ/UI/ネットワーク編

Androidプログラミングレシピ増補改訂版 アーキテクチャ/UI/ネットワーク編

まず、上記の本を参考にしつつ、まとめてみました。

onCreate

  • アクティビティが作成された際に、一度だけ初期化されるべきリソースの初期化を行う
  • 画面のレイアウトや、アクティビティのコンポーネントから呼び出されて通信を行うスレッドといった、アクティビティの中でグローバルに利用されるリソースの初期化を行う
  • 回転などによって破棄されて作り直される場合、前の状態が保存されていれば、onCreate()の引数であるBundleオブジェクトが渡される

onStart

  • アクティビティをユーザーに見せる直前に呼び出される
  • onStart()が呼び出されてからonStop()が呼び出されるまでがユーザーに画面が表示されている期間なので、ここで、バックグラウンド処理のコールバックの登録などを行ったりする
    • たとえば、onStart()メソッドの中でブロードキャストレシーバを登録して、UIに影響を与える変化を起こす通知がこないか監視するようにし、onStop()でその登録を解除したり

onResume

  • アクティビティが復帰する時や、新しいインテントが届いた時に呼び出される
  • アクティビティが最前面に来ていて、ユーザーと対話状態になる直前
    • ここに重い処理を挟むと表示されてしばらく操作できないということになるので、ここで呼び出す処理は可能なかぎり軽い方が良い
  • onPauseと対なので、何らかのデータを編集するためのリソースを編集可能な状態にしたり、アニメーションを動作させるための処理を再開することも...?

onPause

  • Androidが別のアクティビティへ遷移しようとするタイミングで呼び出される
  • まだ保存されていない変更を永続化し、プロセッサのサイクルを消費するアニメーションを停止させるなど
    • ここに重い処理を挟むと遷移するためのボタン操作などを実行してからしばらく画面が起動しないということなので、ここで呼び出す処理は可能なかぎり軽い方が良い
  • ユーザーとの相互作用を停止するための準備

onStop

  • アクティビティがユーザーから見えなくなったときに呼び出される
  • 上記が起こるのは、アクティビティが破棄される場合と、別のアクティビティに隠される場合がある
  • onStart()メソッドの中で設定した、UIに変化を起こすバックグラウンド処理の監視などを解除する

onDestroy

  • アクティビティが破棄される直前に呼び出される
    • 必ず呼び出されるわけではないので永続化などはonPauseのほうがよさそう
  • onCreateで取得したリソースを解放するのが一般的

たとえ話でいうと下記のStackOverflowの疑似コードがなんとなくわかったようなわかっていないような気になれます。

http://stackoverflow.com/questions/4553605/difference-between-onstart-and-onresume

protected void onCreate(...) {
    openGarageDoor();
    unlockCarAndGetIn();
    closeCarDoorAndPutOnSeatBelt();
    putKeyInIgnition();
}

protected void onStart() {
    startEngine();
    changeRadioStation();
    switchOnLightsIfNeeded();
    switchOnWipersIfNeeded();
}

protected void onResume() {
    applyFootbrake();
    releaseHandbrake();
    putCarInGear();
    drive();
}

protected void onPause() {
    putCarInNeutral();
    applyHandbrake();
}

protected void onStop() {
    switchEveryThingOff();
    turnOffEngine();
    removeSeatBeltAndGetOutOfCar();
    lockCar();
}

protected void onDestroy() {
    enterOfficeBuilding();
}

protected void onReachedGroceryStore(...) {
    Intent i = new Intent(ACTION_GET_GROCERIES, ...,  this, GroceryStoreActivity.class);
}

protected void onRestart() {
    unlockCarAndGetIn();
    closeDoorAndPutOnSeatBelt();
    putKeyInIgnition();
}

個人的に、

  • クリックリスナについて、これはユーザーからのタッチイベントの入力にあたり、ユーザーとの相互作用の部分に思えるが、これは、onCreateで設定していいのか、onPauseで解放しなくていいのか?
    • これ経由でUIに変化を及ぼすバックグラウンド処理とか走りそうだけれど?

という疑問があるのですが、クリックリスナはxmlに書いてonCreate()の中のsetContentViewで設定する書き方もある*1ので、一度しか生成されてないViewのリソースの属性の一部という認識で、onCreate()で設定してonDestroy()で削除してもいいのかな、と思いました。

追記

onSaveInstanceStateはUIの状態を再現するために必要なデータの保存を行います。

*1:イベントリスナのインスタンスを生成しない分、こちらのほうが効率的?