【Android/Kotlin】フラグメントのライフサイクルまとめ

#フラグメントのライフサイクル
　まず、フラグメントとは「サブアクティビティ」的なポジションである。アクティビティが成り立っている上で、フラグメントは存在している。ライフサイクルについても同じような関係にあり、アクティビティのライフサイクルが破壊されれば、フラグメントのライフサイクルも破壊されてしまう。あくまでもアクティビティあってのフラグメントである、という事が重要だ。フラグメントとアクティビティのライフサイクルを表した図が以下。
![complete_android_fragment_lifecycle (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658219/8ccf88c1-3499-98ef-28f8-fe32b01c4160.png)
参照：[lifecycle:Activty/Fragment](https://github.com/xxv/android-lifecycle)
　この図は非常に分かりやすく両者のライフサイクルを理解することが出来る。今回は、この図のメインでもある、フラグメントの各コールバックについて簡単に説明をする。

#フラグメント生成編
　これより以下はフラグメントが生成されるときに呼び出されるコールバックメソッドの説明となる。各メソッドにLogを仕込んでいるのは、最終的にライフサイクルを可視化させたいからなので、特に深い理由はない。

##onAttach
　フラグメントのライフサイクルにおいて、最初のメソッド。フラグメントとアクティビティ（コンテクスト）が関連付けられた時に呼ばれる。引数はアクティビティではなく、コンテクスト。他のメソッドにも共通する事であるが、フラグメントは基本的にアクティビティを参照するのではなく、コンテクストを参照する。

```
override fun onAttach(context: Context) {
        Log.d(TAG, "onAttach: called")
        super.onAttach(context)
    }
```
##onCreate

　フラグメントの初期化を行う。アクティビティのonCreateと同じく、条件付きで呼ばれる（ローテーションの時は呼ばないなど）。このメソッドと同時にアクティビティのonCreateが呼ばれると誤解しがちだが実際そうでは無い。フラグメントでこのメソッドが呼ばれている間、アクティビティは絶賛作成中である。

```
override fun onCreate(savedInstanceState: Bundle?) {
        Log.d(TAG, "onCreate: called")
        super.onCreate(savedInstanceState)
    }
```
引数にはバンドルをとる。アクティビティではonCreateにコードを書くことが多いものの、フラグメントではそうではない。アクティビティと異なりsetContentViewメソッドが無いため、レイアウトのウィジェットの参照や作成が出来ないからである。ロジックを書いていくのはまた別のメソッドである。

##onCreatedView
　フラグメントにビューが存在する場合、それを作り出すのがこのメソッド。Fragmentを拡張した時にデフォルトで実装される。レイアウトを膨らませる事が役割である。

```
override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        Log.d(TAG, "onCreateView called")
        return inflater.inflate(R.layout.fragment_main, container, false)
    }
```
返り値はViewであるが、ビューを持たないフラグメントの場合、nullが返される。そのためBundleはNullable。

##onViewCreated
　アクティビティの`onCreate`に相当するコードや、動的にフラグメントのビューを変更する時このメソッドが使われる。onCreateViewでそれを行っても構わないが、通例でonViewCreatedにて行われることが多い。

```
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        Log.d(TAG, "onViewCreated: called")
        super.onViewCreated(view, savedInstanceState)
    }
```

##onActivityCreated
　このメソッドはアクティビティが完全に作成され切ったタイミングで呼ばれる。具体的には、アクティビティがonCreateを実行しきったタイミング。

```
override fun onActivityCreated(savedInstanceState: Bundle?) {
        Log.d(TAG, "onActivityCreated: called")
        super.onActivityCreated(savedInstanceState)
    }
```
従来までこのメソッドにロジックを書くのが主流であったが、最近になって非推奨になった。onActivityCreatedに書かれていた内容はonViewCreatedに移すこと。

##onVewStateRestored

　フラグメントのUIに最終的な変更を加える。最終的な変更というのは、ローテーション以前のEditTextの状態など。

```
override fun onViewStateRestored(savedInstanceState: Bundle?) {
        Log.d(TAG, "onViewStateRestored: called")
        super.onViewStateRestored(savedInstanceState)
    }
```
このメソッドのおかげで、アクティビティと異なりフラグメントは自動で状態の保存と復元を行ってくれる。具体的には、アクティビティであればローテーション後にビューの状態を復元するにはひと手間掛かっていたが、フラグメントはこのメソッドのお陰でそれを自動化してくれている。

##onStart
　フラグメントがユーザーにビューは表示されるものの、完全には機能していない状態の時このメソッドが呼ばれている。

```
override fun onStart() {
        Log.d(TAG, "onStart: called")
        super.onStart()
    }
```
アクティビティのonStartと同じ感じ。

##onResume
　アクティビティとフラグメントの実行を完了し、ユーザーに応答している状態。

```
override fun onResume() {
        Log.d(TAG, "onResume: called")
        super.onResume()
    }
```
このメソッドはアクティビティとフラグメントで同時に実行される。（それぞれのonResumeが実行されている）

#フラグメント破壊編
　これより下は、フラグメント破壊されるときのコールバックメソッドの説明である。

##onPause
　ユーザーが別のタスクに切り替えた時に呼ばれる。この時点でユーザーはフラグメントから離れているが、破壊はされていない。通常はここで保存すべき情報を保存しておく。

```
 override fun onPause() {
        Log.d(TAG, "onPause: called")
        super.onPause()
    }
```
このメソッドはアクティビティとフラグメントのそれぞれで同時に実行される。

##onSaveInstanceState
　このメソッドは必ずしもonPauseの後に呼ばれるとは限らない。基本的にはアクティビティのものと同じで、破壊編の中ならいつでも呼び出すことが可能。

```
override fun onSaveInstanceState(outState: Bundle) {
        Log.d(TAG, "onSaveInstanceState: called")
        super.onSaveInstanceState(outState)
    }
```
このメソッドがあるという事は、onRestoreInstanceStateメソッドもあると思いがちだが、フラグメントにそれは存在しない。その代わり、引数でバンドルを受け取れる生成編のメソッドであれば、どこでも受け取ることが出来る。

##onStop
　このメソッドはフラグメントが停止状態になる時呼ばれる。この時フラグメントは、表示こそされていないものの、破壊までは至っていない。

```
override fun onStop() {
        Log.d(TAG, "onStop: called")
        super.onStop()
    }
```
もしこの時点であってもユーザーが戻ってくれば、onResumeが呼ばれる。その場合でもフラグメントは状態を保持してくれている。

##onDestroyView
　onCreateViewによって膨らまされたビューを引きはがす時に呼ばれる。onCreateViewがnullを返したか否かに関わらず呼ばれる。

```
override fun onDestroyView() {
        Log.d(TAG, "onDestroyView: called")
        super.onDestroyView()
    }
```

##onDestroy
 フラグメントが完全に使用されなくなった時に呼ばれる。フラグメントをクリーンにする。

```
override fun onDestroy() {
        Log.d(TAG, "onDestroy: called")
        super.onDestroy()
    }
```
アクティビティのonDestroyの前に呼ばれる。

##onDettach
　フラグメントがアクティビティから切り離されるときに呼ばれる。

```
override fun onDetach() {
        Log.d(TAG, "onDetach: called")
        super.onDetach()
    }
```
このメソッドもアクティビティのonDestroy前に呼び出される。

#各コールバックメソッドの可視化
　今回説明した各メソッドをそのままフラグメントに張り付けてやるだけで、ライフサイクルの遷移の様子がログに出力される。
<img width="177" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658219/a4a2f139-1337-f547-be3e-24bf69a0f2c5.png">
同時にアクティビティのライフサイクルも可視化させてやれば、それぞれの細かい境界についても理解することが出来るのでお勧めだ。