🧬

【Android】Fragment内に表示されるComposeのライフサイクルを調べる

2025/01/11に公開

概要

Fragment内に表示されているComposeのlifecycleがどのような振る舞いをするのか確認する。

経緯

Jetpack compose化のリファクタリングをしている中で、FragmentのonResumeでViewModelのデータを更新する処理があり、composeだとどのタイミングになるのだろうと悩んだので調査しました。

画面構成

MainActivity は3つのフラグメントを持ち、これらはボトムナビゲーションバーを使って切り替えることができます。
このフラグメントの中で、HomeFragmentはUIコンポーネントにJetpack Composeを使用しています

New Project > Bottom Navigation Views Activityを少しだけ変更して使用しました。

コード

実装箇所

  • HomeFragmentの表示をComposeで実装
  • HomeFragmentとHomeScreen(Compose)のLifecycle eventsにLogを追加

Fragment

class HomeFragment : Fragment() {

  private val TAG = "Fragment"

  override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      Log.d(TAG, "onCreate")
  }

  override fun onCreateView(
      inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
  ): View {
      Log.d(TAG, "onCreateView")
      return ComposeView(requireContext()).apply {
          setContent {
              MaterialTheme {
                  HomeScreen()
              }
          }
      }
  }

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

  override fun onStart() {
      super.onStart()
      Log.d(TAG, "onStart")
  }

  override fun onResume() {
      super.onResume()
      Log.d(TAG, "onResume")
  }

  override fun onPause() {
      super.onPause()
      Log.d(TAG, "onPause")
  }

  override fun onStop() {
      super.onStop()
      Log.d(TAG, "onStop")
  }

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

  override fun onDestroy() {
      super.onDestroy()
      Log.d(TAG, "onDestroy")
  }

  override fun onDetach() {
      super.onDetach()
      Log.d(TAG, "onDetach")
  }
}

Compose

@Composable
fun HomeScreen() {
    val TAG = "Compose"

    LaunchedEffect(Unit) {
        Log.d(TAG, "LaunchedEffect")
    }

    DisposableEffect(Unit) {
        Log.d(TAG, "DisposableEffect")

        onDispose {
            Log.d(TAG, "DisposableEffect: onDispose")
        }
    }

    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        Text(
            text = "This is home screen",
            color = Color.White
        )
    }
}

より詳しい実装を確認したい場合は以下のリポジトリーから
https://github.com/YamazakiYusuke/ComposeLifeCycle/tree/master/app/src/main/java/com/example/composelifecycle

Log結果

※ 見やすいように一部省略しています

// アプリ起動 Fragmentを表示
2025-01-11 18:30:46.196 19420-19420 Fragment D  onCreate
2025-01-11 18:30:46.199 19420-19420 Fragment D  onCreateView
2025-01-11 18:30:46.202 19420-19420 Fragment D  onViewCreated
2025-01-11 18:30:46.245 19420-19420 Fragment D  onStart
2025-01-11 18:30:46.250 19420-19420 Fragment D  onResume
2025-01-11 18:30:46.353 19420-19420 Compose D   DisposableEffect
2025-01-11 18:30:46.461 19420-19420 Compose D   LaunchedEffect

// 他のタブに切り替える
2025-01-11 18:31:09.906 19420-19420 Fragment D  onPause
2025-01-11 18:31:09.907 19420-19420 Fragment D  onStop
2025-01-11 18:31:10.074 19420-19420 Compose D   DisposableEffect: onDispose
2025-01-11 18:31:10.076 19420-19420 Fragment D  onDestroyView

// Homeタブに戻す
2025-01-11 18:31:18.772 19420-19420 Fragment D  onCreateView
2025-01-11 18:31:18.779 19420-19420 Fragment D  onViewCreated
2025-01-11 18:31:18.790 19420-19420 Compose D   DisposableEffect
2025-01-11 18:31:18.791 19420-19420 Fragment D  onStart
2025-01-11 18:31:18.794 19420-19420 Compose D   LaunchedEffect
2025-01-11 18:31:18.948 19420-19420 Fragment D  onResume

結果

onCreateViewのたびにComposeは作り直されるので、onResumeでのデータの再取得はLaunchedEffect(Unit)でやればOK!

Discussion