Androidアプリ開発でActivity(アクティビティ)やFragment(フラグメント)のライフサイクルを理解してコーディングすることはとても重要になります。
ライフサイクルを理解していないままコーディングを進めてしまうと、予期せぬ不具合が起こってしまうことがあります。
例えば、次のような事が起こる場合があります。
- 画面回転すると画面に表示させているデータが意図しないものになってしまう
- 画面を行き来するとメモリが増え続けてしまう
ActivityやFragmentのライフサイクルは覚えているつもりなのですが、正確な流れを確認したくなることがあるので調査&整理してみました。
ライフサイクルとは
そもそもですが、ライフサイクルとは何なのでしょうか?
ざっくりとした説明ですが、ライフサイクルとは産まれてから消滅するまでの一連の流れのことになります。
私たち人間に当てはめて考えると、
- 誕生→小学生→中学生→高校生→(いろいろあり)→亡くなる
だいたいこの様なイメージだと思います。
人間の一生のことですね。
このような一連の流れのことをライフサイクルといいます。
今回のActivityやFragmentの場合は次のような流れがあります。
- 生成→開始→停止→消滅
それでは詳しく見ていきます。
Activityのライフサイクル
Activity のライフサイクルは次のようになります。
※画像はandroidのdevelopersサイトからお借りしました。
以下に各メソッドの大枠を記載します。
onCreate()
Activityが作成されたときに呼び出されます。
このタイミングでビューを作成したり、各種設定を行います。
onRestart()
Activityが停止され、非表示の状態から再び画面に表示されようとした場合に呼びだされます。
例えば、アプリがレジュームされてActivityがフォアグラウンドになる際や、別のActivityが終了して最前面に戻ってくる際に呼び出されます。
onStart()
Activityがユーザーに見えるようになったときに呼び出されます。
このタイミングでは見えるようになっただけで、まだユーザからの操作は受け付けていません。
onResume()
Activityがユーザーからの操作を受付始めるときに呼び出されます。
onPause()
Activityがフォアグラウンド状態を失ったときや停止する前に呼び出されます。
例えば、アプリがサスペンドされる前や別の Activity が起動されて遷移する前、Activityが終了する前に呼び出されます。
onStop()
Activityがユーザーに表示されなくなったときに呼び出されます。
例えば、アプリがサスペンドされた時や別のActivityが起動されて遷移した時、Activityが終了する時に呼び出されます。
onDestroy()
Activityが破棄される前に呼び出されます。
Fragmentのライフサイクル
Fragmentのライフサイクルは次のようになります。
※画像はandroidのdevelopersサイトからお借りしました。
以下に各メソッドの大枠を記載します。
onAttach()
FragmentがActivityと関連付けられたときに呼び出されます。
onCreate()
Fragmentが作成されたときに呼び出されます。
onCreateView()
Fragmentに関連付けられたビューを作成する際に呼び出されます。
onActivityCreated()
Activityの onCreate() が完了した際に呼び出されるます。
onStart()
Fragmentがユーザーに見えるようになったときに呼び出されます。
このタイミングでは見えるようになっただけで、まだユーザからの操作は受け付けていません。
onResume()
Fragmentがユーザーからの操作を受付開始するときに呼び出されます。
onPause()
Fragment がフォアグラウンド状態を失ったときや停止する前に呼び出されます。
例えば、アプリがサスペンドされる前や別のFragmentが起動されて遷移する前、Fragmentが終了する前に呼び出されます。
onStop()
Fragmentがユーザーに表示されなくなったときに呼び出されます。
例えば、アプリがサスペンドされた時や別のFragmentが起動されて遷移した時、Fragmentが終了する時に呼び出されます。
onDestroyView()
Activityが破棄される前に呼び出されます。
Fragmentに関連付けられたビューが削除されたときに呼び出されます。
onDestroy()
Fragmentが破棄される前に呼び出されます。
onDetach()
FragmentとActivityとの関連付けが解除されたときに呼び出されます。
Fragmentのライフサイクルについて補足事項
developersのFragmentのドキュメント内、 onCreateView 部分に以下の記載があります。
It is recommended to only inflate the layout in this method and move logic that operates on the returned View to onViewCreated(View, Bundle).
onCreateViewではレイアウトをinflateするだけで、ビューで動作するロジック関係はonViewCreatedでやることを推奨しているようです。
可能な限り守りながら実装を進めるのが良いでしょう。
ActivityとFragmentのライフサイクルについて実際の動きを確認
ドキュメントに書かれている流れになるのか実際に確認してみます。
今回作成したサンプルアプリのソースコードは githubのLifecycleSample に置いてあります。
今回、画面遷移時の遷移元と遷移先を含めたライフサイクルのlを合わせて確認したかったため、Activityを3クラス、Fragmentを3クラス用意しました。
クラスの構成は次のようになっています。
BaseActivity、BaseFragmentのライフサイクルのイベント時にログを出力しています。
FirstとSecondはBaseクラスを継承しているだけで、(画面遷移の処理はありますが)特殊なことはしていません。
動作させるとドキュメントに記載されているライフサイクルの順番でログが出力されていることがわかると思います。
画面を切り替えるだけでなく、アプリをサスペンドしたりレジュームさせたりすると、画面遷移するときとは違った動きになっていることがわかります。
画面遷移させたタイミングで何か処理をおこなうということはよくあるかと思うので、遷移するときの遷移元と遷移先のライフサイクルの流れも確認しておくことは大事だと思います。
さいごに
今回、ActivityとFragmentのライフサイクルについて触れましが、基本的なタイミングで呼び出されるライフサイクルのイベントのみ触れています。
細かく見ていくと実は更に多くのイベントがあります。
また、ActivityとFragmentだけでなく、ViewやViewModelなど様々なものにライフサイクルは存在するので、そちらも理解しておくと良いと良さそうですね。