Fragment Lifecycle: 基礎、onCreateViewとonViewCreatedメソッド

著者: IT Sectr 公開日: 2026-03-04 読了時間: 12 分

Fragment Lifecycleは、AndroidがFragmentのライフタイム全体にわたって呼び出すコールバックメソッドの厳密に定義されたシーケンスです:生成(onAttach)から完全な削除(onDetach)まで。FragmentのライフサイクルはActivityよりも複雑で、11の状態と7つの主要なコールバックを含みます。Fragment LifecycleはFragmentManagerを通じて管理され、それを含むActivityのライフサイクルと密接に関連しています。Googleによると、FragmentはAPI Level 21+で動作するAndroidアプリケーションの74%で使用されており、プロフェッショナルなAndroid開発にはFragment Lifecycleの理解が必須です。Fragment Lifecycleに関するAndroidドキュメントは、すべての状態と呼び出しの保証を説明しています。

重要なポイント

  • Fragment Lifecycleには11のコールバックが含まれます:onAttach、onCreate、onCreateView、onViewCreated、onStart、onResume、onPause、onStop、onDestroyView、onDestroy、onDetach。
  • FragmentManagerはFragmentの状態を管理し、トランザクション中に正しい呼び出し順序を保証します。
  • onCreateViewとonViewCreatedは、Fragment UIを作成および構成するための主要なメソッドです。
  • Fragmentは(画面回転時に)自身のActivityよりも長く存続し、onSaveInstanceStateを介して状態を復元できます。
  • viewLifecycleOwner — Fragment View用の独立したLifecycleで、onDestroyViewで破棄されます。

Fragment Lifecycle: ライフサイクルの基礎

Fragment Lifecycleは、各Fragmentインスタンスが生成から破棄までに経由する相互接続された状態とメソッドのセットです。Activityとは異なり、Fragmentのライフサイクルは2つのコンテキストに結びついています:Fragment自体(onAttachからonDetachまで生存)とそのView(onCreateViewからonDestroyViewまで生存)です。この分離はFragmentの主要な機能であり、Fragment自体を破棄せずに画面回転時のView破棄に耐えることを可能にします。

Fragmentコールバックの完全なシーケンス:

  • onAttach(Context) — FragmentがActivityにアタッチされます。最初に呼び出されます。ContextはホストActivityです。
  • onCreate(Bundle) — Fragmentが初期化されます。ここでViewModelが作成され、アダプターが構成されます。
  • onCreateView(LayoutInflater, ViewGroup, Bundle) — FragmentのView階層が作成されます。ルートViewを返します。
  • onViewCreated(View, Bundle) — Viewが作成されました。ここでUI要素の構成やLiveDataの購読設定を行います。
  • onStart() — Fragmentが可視になります。アニメーションが開始され、センサーが登録されます。
  • onResume() — Fragmentがアクティブになり、ユーザーと対話します。
  • onPause() — Fragmentがフォーカスを失います。アニメーションが停止します。
  • onStop() — Fragmentが非可視になります。重要でないリソースが解放されます。
  • onDestroyView() — View階層が破棄されます。Viewへの参照がnullに設定されます。
  • onDestroy() — Fragmentが破棄されます。viewModelScopeにないコルーチンがキャンセルされます。
  • onDetach() — FragmentがActivityからデタッチされます。最終クリーンアップ。

Googleによると、最新のアプリケーションにおける平均的なフラグメントは、ユーザーセッションごとに3〜5回フルサイクルを経由します(画面回転とナビゲーションのため)。すべてのフェーズの正しい処理がUIの安定性の基盤です。

Fragmentの状態:INITIALIZEDからDESTROYEDまで

FragmentManagerはFragmentを5つの主要な状態で管理します。これらはFragment.Stateクラスで定義されています。各状態は、実行されたコールバックの特定のセットに対応します。

状態意味実行済みコールバック
INITIALIZEDFragmentは作成されましたが、Viewはまだ利用できませんonAttach、onCreate
CREATEDViewは作成されましたが、Fragmentは可視ではありません+ onCreateView、onViewCreated
STARTEDFragmentは可視ですが、アクティブではありません+ onStart
RESUMEDFragmentはアクティブで、ユーザーと対話しています+ onResume
DESTROYEDFragmentは破棄されました+ onDestroyView、onDestroy、onDetach

FragmentManagerは、ユーザーアクションとシステムイベントに基づいてFragmentを状態間で移動させます。コンテナにFragmentを追加すると、INITIALIZED → CREATED → STARTED → RESUMEDの順に経由します。削除時は、RESUMED → STARTED → CREATED → DESTROYEDとなります。

CREATED状態は特別です:Viewは破棄される可能性がありますが(onDestroyView後)、Fragment自体はCREATED状態のままです(onDestroyView後、onDestroy前)。これにより、FragmentManagerはViewなしでFragmentをメモリに保持でき、画面回転に耐えるために必要です。

Fragment LifecycleとActivity Lifecycleの違い

Fragment LifecycleとActivity Lifecycleは密接に関連していますが、根本的な違いがあります。Fragmentは常にActivity内で生存し、そのライフサイクルはホストActivityに依存しますが、同一ではありません。

側面ActivityFragment
コールバック数7(onCreate … onDestroy)11(onAttach … onDetach)
View用の独立したLifecycleなしあり(viewLifecycleOwner)
回転に耐えるなし(破棄される)あり(ViewModel + Fragmentは生存)
ホストへの依存なしActivity Lifecycleに依存
状態保存onSaveInstanceStateonSaveInstanceState(Fragmentレベル)
管理システムFragmentManager

主な実用的な違い:画面回転時、Activityは完全に破棄(onDestroy)されて再作成(onCreate)されます。Fragmentは回転時にonDestroyView(View破棄)→ onCreateView(View再作成)を経由しますが、Fragment自体とそのViewModelは生存し続けます。これにより、Fragmentは設定変更に耐える必要があるUIロジックにとって理想的なコンテナとなります。

画面回転時の呼び出し順序:Activity.onPause → Fragment.onPause → Activity.onStop → Fragment.onStop → Activity.onDestroy → Fragment.onDestroyView →(Activity破棄)→ Activity.onCreate → Fragment.onAttach → Fragment.onCreate → Fragment.onCreateView → Fragment.onViewCreated → Activity.onStart → Fragment.onStart → Activity.onResume → Fragment.onResume。

FragmentManager:状態管理とトランザクション

FragmentManagerは、フラグメントの追加、削除、置換、およびそれらの状態管理を担当する中心的なクラスです。FragmentManagerはBackStackを維持し、トランザクション中の正しいコールバック順序を保証します。各Activityと各ネストされたFragmentには独自のFragmentManagerがあります。

FragmentManagerの主要な操作:

  • beginTransaction() — 操作グループのトランザクションを開きます。
  • add() — コンテナにFragmentを追加します。FragmentはRESUMEDまで完全なライフサイクルを経由します。
  • replace() — 現在のFragmentを新しいものに置き換えます。remove() + add()と同等です。
  • remove() — Fragmentを削除します。FragmentはRESUMEDからDESTROYEDまでのライフサイクルを経由します。
  • hide()/show() — Viewを破棄せずにFragmentを非表示/表示します。非表示時にFragmentはSTARTEDに移行し、表示時にRESUMEDに戻ります。
  • detach()/attach() — Fragmentをデタッチ/アタッチします。detachはViewを破棄(onDestroyView)し、attachは再作成(onCreateView)します。
  • addToBackStack() — 戻るナビゲーションのためにトランザクションをBackStackに追加します。

BackStackはFragmentManagerのトランザクションスタックです。システムの戻るボタンを押すと、BackStackの最後のトランザクションがロールバックされます(popBackStack())。popBackStackで削除されたFragmentは復元されます。BackStackが空の場合、戻るを押すとActivityが終了します。

Googleによると、Fragmentの問題(重複、空画面、IllegalStateException)の78%はFragmentManagerの誤った使用に関連しています。主要なルール:コンテキストに応じて、commit()(非同期)またはcommitNow()(同期)を介してトランザクションを実行します。commit()は複数のトランザクション下で正しい順序を保証します。

Fragmentの状態保存:onSaveInstanceState

FragmentはonSaveInstanceStateを介して独自の状態保存メカニズムをサポートしています。これはActivityから独立して動作します。FragmentはBundleに状態を保存し、復元時にonCreateとonCreateViewに渡されます。

Fragmentが状態を保存するタイミング:

  • 画面回転時 — Viewは破棄され、FragmentはBundleに状態を保存します。
  • プロセス終了後にFragmentがActivityに再アタッチされる時。
  • ActivityからonSaveInstanceStateが呼び出された時(システムは保存をすべての子フラグメントに伝播します)。

最新のアプローチ:Fragmentの状態保存にはViewModelのSavedStateHandleを使用します。SavedStateHandleは、手動のonSaveInstanceStateを必要とせずに、画面回転時およびプロセス終了時にデータを自動的に保存および復元します。GoogleはFragmentでのUI状態保存の推奨方法としてSavedStateHandleを推奨しています。

setRetainInstance(Fragment 1.3以降非推奨):以前はFragmentをsetRetainInstance(true)を介して画面回転時に保持できました。このアプローチはViewModel + SavedStateHandleに置き換えられました。これらはより信頼性高く動作し、特別な構成を必要としません。

viewLifecycleOwner:Viewの独立したライフサイクル

viewLifecycleOwnerは、Fragment Viewに結びついたLifecycleです(onCreateViewからonDestroyViewまで)。これは根本的に重要な概念です:viewLifecycleOwnerを介して行われたLiveData/Flowの購読は、Viewが破棄される(onDestroyView)と自動的にキャンセルされますが、Fragment自体には影響しません。

viewLifecycleOwnerとFragment lifecycleの違い:

  • lifecycle(Fragment) — onAttachからonDetachまで生存します。View破棄後も購読はアクティブなままです。
  • viewLifecycleOwner — onCreateViewからonDestroyViewまで生存します。View破棄時に購読がキャンセルされます。

これが重要な理由:Fragment lifecycle(this)を介してLiveDataを購読すると、onDestroyView後も購読はアクティブなままで、LiveDataはnullのViewを更新しようとしてNPEを引き起こします。viewLifecycleOwnerを介した購読は、onDestroyView後にUI更新が発生しないことを保証します。

ルール:Fragmentでは、LiveData、Flow、およびUI関連のコルーチンの購読には常にviewLifecycleOwnerを使用します。ViewModelのコルーチンにはviewModelScopeを使用します。これはFragmentではなくViewModelに結びついています。

KotlinでのFragmentコード例

例1:onViewCreatedとviewLifecycleOwnerを使用した基本Fragment

正しいUI初期化とviewLifecycleOwnerを介したLiveData購読を示します。

kotlin
class UserListFragment : Fragment() {
    private val viewModel: UserListViewModel by viewModels()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return inflater.inflate(R.layout.fragment_user_list, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val button: Button = view.findViewById(R.id.load_button)
        button.setOnClickListener { viewModel.loadUsers() }
        viewModel.users.observe(viewLifecycleOwner) { users ->
            Log.d("UserListFragment", "リスト更新中: ${users.size} ユーザー")
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.d("UserListFragment", "onDestroyView: Viewが破棄されました")
    }
}

FragmentはonCreateViewでレイアウトをインフレートし、onViewCreatedでUIを構成してLiveDataを購読します。viewLifecycleOwnerを介した購読は、リークを防ぐための必須要件です。onDestroyViewはViewの破棄をログに記録します — Fragmentが画面回転に耐えることの確認です。

例2:FragmentManagerとトランザクションを使用したFragment

ActivityでのFragmentManagerを介したFragmentの追加、BackStackを使用した置換と復元を示します。

kotlin
class HostActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_host)
        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .add(R.id.fragment_container, HomeFragment())
                .addToBackStack(null)
                .commit()
        }
    }

    fun openDetail(userId: String) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.fragment_container, DetailFragment.newInstance(userId))
            .addToBackStack(null)
            .commit()
    }

    override fun onBackPressed() {
        if (supportFragmentManager.backStackEntryCount > 0) {
            supportFragmentManager.popBackStack()
        } else {
            super.onBackPressed()
        }
    }
}

class DetailFragment : Fragment() {
    companion object {
        fun newInstance(userId: String): DetailFragment {
            return DetailFragment().apply {
                arguments = Bundle().apply { putString("user_id", userId) }
            }
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val userId = arguments?.getString("user_id")
        Log.d("DetailFragment", "ユーザー詳細を読み込み中: $userId")
    }
}

ActivityはsupportFragmentManagerを使用してフラグメントを管理します。BackStackを使用したadd()トランザクションは、戻るボタン押下時にHomeFragmentが復元されることを保証します。openDetail()は現在のFragmentを引数付きのDetailFragmentに置き換えます。savedInstanceState == nullのチェックは、画面回転時のフラグメント重複を防ぎます。

例3:LifecycleObserverとStateFlowを使用したFragment

リアクティブなUI更新のためのviewLifecycleOwnerを使用したFragmentでのFlowとStateFlowの使用。

kotlin
class SearchFragment : Fragment() {
    private val viewModel: SearchViewModel by viewModels()
    private var binding: FragmentSearchBinding? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentSearchBinding.inflate(inflater, container, false)
        return binding!!.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding?.searchButton?.setOnClickListener {
            viewModel.search(binding?.queryInput?.text.toString())
        }
        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.searchResults.collectLatest { results ->
                Log.d("SearchFragment", "検索結果: ${results.size}")
            }
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        binding = null
    }
}

FragmentはViewへのアクセスにView Bindingを使用します。viewLifecycleOwner.lifecycleScope.launchコルーチンはView破棄時に自動的にキャンセルされます。リークを防ぐためにonDestroyViewでbindingをnullに設定します。StateFlowはView再作成時にデータの最新性を保証します。

よくある質問

onViewCreatedとonCreateViewの違いは何ですか?

onCreateViewはFragmentのルートViewを作成して返します。onViewCreatedはView作成直後に呼び出され、Viewが完全に初期化されて構成(findViewById、購読)の準備ができていることを保証します。GoogleはonCreateViewではレイアウトのインフレートのみを行い、すべてのUI構成はonViewCreatedで行うことを推奨しています。

Fragmentは実際にいつ破棄されますか — onDestroyですか、onDetachですか?

onDestroy — Fragmentがオブジェクトとして破棄されます(ViewModelがクリアされ、コルーチンがキャンセルされます)。onDetachは最後のコールバックで、その後FragmentがActivityからデタッチされます。実質的にすべてのリソースはonDestroyView(View)とonDestroy(Fragment)で解放されるべきです。onDetachはActivityへの参照をクリーンアップするためのものです。

画面回転後にFragmentが消えるのはなぜですか?

FragmentがBackStackに保存されたトランザクションを介してFragmentManagerに追加されなかった場合、またはActivityがonCreateでFragmentManagerを復元しない場合にFragmentは消えます。解決策:savedInstanceState == nullのチェックを伴って、onCreate内でsupportFragmentManager.beginTransaction().add()を介してプログラム的にFragmentを追加します。

FragmentはActivityなしで存在できますか?

いいえ。Fragmentは常にFragmentManagerを介してActivityに結びついています。画面回転時でも、Activityは再作成され、Fragmentは新しいActivityに再アタッチされます。Activityの外部でFragmentを作成することは不可能です — Fragmentコンストラクターはシステム復元のために空のコンストラクターを必要とします。

ネストされたフラグメントとは何ですか?なぜ必要ですか?

ネストされたフラグメント(入れ子フラグメント)は、別のFragment内のFragmentです。複雑な画面(タブパネル、タブ付きパネル、マスター詳細)を構築するために使用されます。ネストされたフラグメントは子FragmentManager(childFragmentManager)によって管理されます。Googleはパフォーマンスの問題を避けるために2レベル以上のネストを推奨していません。

まとめ

  • Fragment Lifecycleには11のコールバックが含まれます:onAttach → onCreate → onCreateView → onViewCreated → onStart → onResume → onPause → onStop → onDestroyView → onDestroy → onDetach。
  • FragmentManagerはFragmentの状態(INITIALIZED → CREATED → STARTED → RESUMED → DESTROYED)とトランザクションのBackStackを管理します。
  • Fragmentは画面回転に耐えます — Viewは破棄されます(onDestroyView)が、FragmentとViewModelは生存し続けます。
  • viewLifecycleOwnerはFragment Viewのための独立したLifecycleです。LiveDataとUIコルーチンの購読に必須です。
  • Fragmentの状態保存 — onSaveInstanceStateまたはViewModelのSavedStateHandleを介して行います。
  • Fragmentトランザクションは、commit()(非同期)またはcommitNow()(同期)を使用してFragmentManagerを介して実行されます。
  • メモリリークを防ぐために、onDestroyViewで常にbindingとView参照をnullに設定してください。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください