Jetpack Navigation を Navigation Compose に移行する

Navigation Compose API を使用すると、Jetpack Navigation のコンポーネント、インフラストラクチャ、機能を活用しながら、Compose アプリのコンポーザブル間を移動できます。

このページでは、フラグメント ベースの Jetpack Navigation から より大規模なビューベースの UI を Jetpack に移行するための Navigation Compose 作成。

移行の前提条件

Navigation Compose に移行する際は、すべてのインフラストラクチャを 対応する画面コンポーザブルを持つフラグメントをご覧ください。画面コンポーザブルには以下を含めることができます Compose と View のコンテンツが混在しているが、すべてのナビゲーション デスティネーションは コンポーザブルを使用して Navigation Compose の移行を有効にします。それまでは、相互運用性 View と Compose のコードベースで フラグメント ベースの Navigation コンポーネントを引き続き使用する必要があります。詳しくは、ナビゲーションの相互運用に関するドキュメントをご覧ください。 情報です。

Compose のみのアプリで Navigation Compose を使用する必要はありません。コンポーズ可能なコンテンツをホストするためのフラグメントを保持している限り、フラグメント ベースの Navigation コンポーネント引き続き使用できます。

移行手順

推奨される移行戦略に沿って移行する場合でも、別の方法で移行する場合でも、すべてのナビゲーション デスティネーションが画面コンポーザブルになり、フラグメントがコンポーザブル コンテナとしてのみ機能するようになります。この段階で、Navigation Compose に移行できます。

アプリがすでに UDF 設計パターンと Google のガイド アーキテクチャでは、Jetpack Compose と Navigation Compose に移行する際は、 UI レイヤ以外のレイヤの大幅なリファクタリングが必要になる。

Navigation Compose に移行する手順は次のとおりです。

  1. アプリに Navigation Compose の依存関係を追加します。
  2. App-level コンポーザブルを作成し、Compose エントリ ポイントとして Activity に追加して、ビュー レイアウトの設定を置き換えます。

    class SampleActivity : ComponentActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            // setContentView<ActivitySampleBinding>(this, R.layout.activity_sample)
            setContent {
                SampleApp(/* ... */)
            }
        }
    }

  3. ナビゲーションの各デスティネーションのタイプを作成します。データを必要としないデスティネーションには data object を使用し、データを必要とするデスティネーションには data class または class を使用します。

    @Serializable data object First
    @Serializable data class Second(val id: String)
    @Serializable data object Third
    

  4. NavController は、これを参照する必要があるすべてのコンポーザブルがアクセスできる場所に設定します(通常は App コンポーザブル内)。このアプローチは、状態ホイスティングの原則に従います。 これにより、NavController を信頼できる情報源として使用できるようになります。 コンポーズ可能な画面間の移動とバックスタックの維持:

    @Composable
    fun SampleApp() {
        val navController = rememberNavController()
        // ...
    }

  5. App コンポーザブル内にアプリの NavHost を作成し、navController を渡します。

    @Composable
    fun SampleApp() {
        val navController = rememberNavController()
    
        SampleNavHost(navController = navController)
    }
    
    @Composable
    fun SampleNavHost(
        navController: NavHostController
    ) {
        NavHost(navController = navController, startDestination = First) {
            // ...
        }
    }

  6. composable デスティネーションを追加して、ナビゲーション グラフを作成します。各 画面はすでに Compose に移行されています。このステップでは、 画面コンポーザブルをフラグメントから抽出して composable 件の目的地:

    class FirstFragment : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View {
            return ComposeView(requireContext()).apply {
                setContent {
                    // FirstScreen(...) EXTRACT FROM HERE
                }
            }
        }
    }
    
    @Composable
    fun SampleNavHost(
        navController: NavHostController
    ) {
        NavHost(navController = navController, startDestination = First) {
            composable<First> {
                FirstScreen(/* ... */) // EXTRACT TO HERE
            }
            composable<Second> {
                SecondScreen(/* ... */)
            }
            // ...
        }
    }

  7. Compose UI の設計のガイダンスに沿って操作した場合、 具体的には、ViewModel とナビゲーション イベントを 作成したら、次は ViewModel を指定する方法を変更して、 各画面コンポーザブルを使用します。多くの場合、hiltViewModel を介して Hilt インジェクションと、Compose と Navigation との統合ポイントを使用できます。

    @Composable
    fun FirstScreen(
        // viewModel: FirstViewModel = viewModel(),
        viewModel: FirstViewModel = hiltViewModel(),
        onButtonClick: () -> Unit = {},
    ) {
        // ...
    }

  8. すべての findNavController() ナビゲーション呼び出しを navController に置き換える ナビゲーション イベントとして各コンポーザブルの画面に渡します。代わりに、 navController 全体を渡すよりも効率的です。このアプローチは、コンポーズ可能な関数から呼び出し元にイベントを公開するベスト プラクティスに従い、navController を信頼できる唯一の情報源として保持します。

    データを宛先に渡すには、その宛先に定義されているルートクラスのインスタンスを作成します。その後、アプリケーションから直接入手するか、 デスティネーションのバックスタック エントリから、または ViewModel を使用して SavedStateHandle.toRoute()

    @Composable
    fun SampleNavHost(
        navController: NavHostController
    ) {
        NavHost(navController = navController, startDestination = First) {
            composable<First> {
                FirstScreen(
                    onButtonClick = {
                        // findNavController().navigate(firstScreenToSecondScreenAction)
                        navController.navigate(Second(id = "ABC"))
                    }
                )
            }
            composable<Second> { backStackEntry ->
                val secondRoute = backStackEntry.toRoute<Second>()
                SecondScreen(
                    id = secondRoute.id,
                    onIconClick = {
                        // findNavController().navigate(secondScreenToThirdScreenAction)
                        navController.navigate(Third)
                    }
                )
            }
            // ...
        }
    }

  9. すべての Fragment、関連する XML レイアウト、不要なナビゲーションなどのリソース、古い Fragment と Jetpack Navigation の依存関係を削除します。

Navigation Compose に関する詳細な手順については、設定のドキュメントをご覧ください。

一般的なユースケース

どの Navigation コンポーネントを使用する場合でも、同じナビゲーションの原則が適用されます

移行の一般的なユースケースは次のとおりです。

これらのユースケースの詳細については、Google Cloud による Compose にあります。

操作時に複雑なデータを取得

ナビゲーション時には、複雑なデータ オブジェクトを渡さないことを強くおすすめします。 代わりに、ナビゲーション アクションの実行時に引数として必要最低限の情報(一意の識別子やその他の形式の ID など)を渡します。すべきこと 複雑なオブジェクトを、信頼できる唯一の情報源にデータとして格納します。 レイヤです。詳細については、ナビゲーション時の複雑なデータの取得をご覧ください。

フラグメントが複雑なオブジェクトを引数として渡している場合は、まずコードをリファクタリングして、これらのオブジェクトをデータレイヤに保存および取得できるようにすることを検討してください。Now in Android リポジトリを参照し、 説明します。

制限事項

このセクションでは、Navigation Compose の現在の制限事項について説明します。

Navigation Compose への段階的な移行

現時点では、コードでフラグメントをデスティネーションとして使用しながら Navigation Compose を使用することはできません。Navigation Compose の使用を開始するには、 デスティネーションはコンポーザブルにする必要がありますこの機能リクエストは Issue Tracker をご覧ください。

遷移アニメーション

Navigation 2.7.0-alpha01 以降、以前は AnimatedNavHost でサポートされていたカスタム遷移の設定が、NavHost で直接サポートされるようになりました。詳しくは、リリースノートをご覧ください。

詳細

Navigation Compose への移行について詳しくは、以下をご覧ください。 リソース:

  • Navigation Compose Codelab: Navigation Compose の基本について学びます。 実践演習も行います
  • Now in Android リポジトリ: Kotlin と Jetpack Compose のみで構築された、完全に機能する Android アプリです。Android の設計と開発のベスト プラクティスに準拠しており、Navigation Compose が含まれています。
  • Sunflower を Jetpack Compose に移行する: Sunflower サンプルアプリをビューから Compose に移行する過程を記述したブログ投稿です。Navigation Compose への移行も含まれています。
  • すべてのスクリーン向けの Jetnews: Jetnews サンプルのリファクタリングと移行を行い、 Jetpack Compose と Navigation Compose。