Memigrasikan Jetpack Navigation ke Navigation Compose

Navigation Compose API memungkinkan Anda menavigasi antar-composable dalam aplikasi Compose, sekaligus memanfaatkan komponen, infrastruktur, dan komponen Navigasi Jetpack.

Halaman ini menjelaskan cara bermigrasi dari Navigasi Jetpack berbasis Fragment ke Navigation Compose, sebagai bagian dari migrasi UI berbasis View yang lebih besar ke Jetpack Compose.

Prasyarat migrasi

Anda dapat bermigrasi ke Navigation Compose setelah dapat mengganti semua Fragment dengan composable layar yang sesuai. Composable layar dapat berisi gabungan konten Compose dan View, tetapi semua tujuan navigasi harus berupa composable untuk mengaktifkan migrasi Navigation Compose. Sebelum itu, Anda harus terus menggunakan komponen Navigasi berbasis Fragment di codebase View interop dan Compose. Lihat dokumentasi interop navigasi untuk informasi selengkapnya.

Menggunakan Navigation Compose di aplikasi khusus Compose bukanlah prasyarat. Anda dapat terus menggunakan Komponen Navigasi berbasis Fragmen, selama Anda mempertahankan Fragment untuk menghosting konten composable.

Langkah migrasi

Baik Anda mengikuti strategi migrasi yang direkomendasikan maupun menggunakan pendekatan lain, Anda akan mencapai titik di mana semua tujuan navigasi merupakan composable layar, dengan Fragmen yang hanya bertindak sebagai penampung composable. Pada tahap ini, Anda dapat bermigrasi ke Navigation Compose.

Jika aplikasi Anda sudah mengikuti pola desain UDF dan panduan arsitektur kami, migrasi ke Jetpack Compose dan Navigation Compose seharusnya tidak memerlukan pemfaktoran ulang utama dari lapisan lain aplikasi Anda, selain lapisan UI.

Untuk bermigrasi ke Navigation Compose, ikuti langkah-langkah berikut:

  1. Tambahkan dependensi Navigation Compose ke aplikasi Anda.
  2. Buat composable App-level dan tambahkan ke Activity sebagai titik entri Compose, yang menggantikan penyiapan tata letak View:

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

  3. Siapkan NavController di tempat semua composable yang perlu mereferensikannya memiliki akses ke composable tersebut (biasanya di dalam composable App). Pendekatan ini mengikuti prinsip pengangkatan status dan memungkinkan Anda menggunakan NavController sebagai sumber kebenaran untuk menavigasi antara layar composable dan mempertahankan data sebelumnya:

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

  4. Buat NavHost aplikasi di dalam composable Aplikasi dan teruskan navController:

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

  5. Tambahkan tujuan composable untuk membuat grafik navigasi. Jika setiap layar sebelumnya telah dimigrasikan ke Compose, langkah ini hanya terdiri dari mengekstrak composable layar ini dari Fragment Anda ke tujuan 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(/* ... */)
            }
            // ...
        }
    }

  6. Jika Anda mengikuti panduan tentang merancangan UI Compose, khususnya cara ViewModel dan peristiwa navigasi diteruskan ke composable, langkah berikutnya adalah mengubah cara Anda menyediakan ViewModel ke setiap composable layar. Anda sering menggunakan injeksi Hilt dan titik integrasinya dengan Compose dan Navigasi melalui hiltViewModel:

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

  7. Ganti semua panggilan navigasi findNavController() dengan panggilan navController dan teruskan ini sebagai peristiwa navigasi ke setiap layar composable, bukan meneruskan seluruh navController. Pendekatan ini mengikuti praktik terbaik mengekspos peristiwa dari fungsi composable ke pemanggil dan menjaga navController sebagai satu-satunya sumber tepercaya.

    1. Jika sebelumnya Anda telah menggunakan plugin Safe Args untuk membuat rute dan tindakan navigasi, ganti dengan route — Jalur String ke composable Anda yang unik untuk setiap tujuan.
    2. Untuk mengganti Safe Args saat meneruskan data, lihat Menavigasi dengan argumen.
    3. Untuk keamanan jenis di Navigation Compose, baca bagian Safe Args di bawah.

      @Composable
      fun SampleNavHost(
          navController: NavHostController
      ) {
          NavHost(navController = navController, startDestination = "first") {
              composable("first") {
                  FirstScreen(
                      onButtonClick = {
                          // findNavController().navigate(firstScreenToSecondScreenAction)
                          navController.navigate("second_screen_route")
                      }
                  )
              }
              composable("second") {
                  SecondScreen(
                      onIconClick = {
                          // findNavController().navigate(secondScreenToThirdScreenAction)
                          navController.navigate("third_screen_route")
                      }
                  )
              }
              // ...
          }
      }

  8. Hapus semua Fragment, tata letak XML yang relevan, navigasi yang tidak diperlukan dan resource lainnya, serta dependensi Fragment dan Jetpack Navigation yang tidak berlaku.

Anda dapat menemukan langkah yang sama dengan detail selengkapnya terkait Navigation Compose di Dokumentasi penyiapan.

Kasus penggunaan umum

Apa pun komponen Navigasi yang Anda gunakan, prinsip navigasi yang sama akan berlaku.

Kasus penggunaan umum saat melakukan migrasi meliputi:

Untuk mengetahui informasi selengkapnya tentang kasus penggunaan ini, lihat Menavigasi dengan Compose.

Safe Args

Tidak seperti Jetpack Navigation, Navigation Compose tidak mendukung penggunaan plugin Safe Args untuk pembuatan kode. Sebagai gantinya, Anda dapat mencapai keamanan jenis dengan Navigation Compose dengan membuat struktur kode agar aman dari error jenis saat runtime.

Mengambil data yang kompleks saat menavigasi

Navigation Compose berbasis rute String dan, tidak seperti Jetpack Navigation, tidak mendukung penerusan Parcelable dan Serializable kustom sebagai argumen.

Sebaiknya Anda tidak meneruskan objek data yang kompleks saat menavigasi. Sebagai gantinya, teruskan informasi minimum yang diperlukan, seperti ID unik atau bentuk ID lainnya, sebagai argumen saat melakukan tindakan navigasi. Anda harus menyimpan objek kompleks sebagai data dalam satu sumber tepercaya, seperti lapisan data. Untuk mengetahui informasi selengkapnya, baca artikel Mengambil data kompleks saat menavigasi.

Jika Fragmen Anda meneruskan objek kompleks sebagai argumen, pertimbangkan untuk memfaktorkan ulang kode terlebih dahulu, dengan cara yang memungkinkan penyimpanan dan pengambilan objek ini dari lapisan data. Lihat repositori Now in Android untuk mengetahui contohnya.

Batasan

Bagian ini menjelaskan batasan saat ini untuk Navigation Compose.

Migrasi inkremental ke Navigation Compose

Saat ini, Anda tidak dapat menggunakan Navigation Compose saat masih menggunakan Fragment sebagai tujuan dalam kode Anda. Untuk mulai menggunakan Navigation Compose, semua tujuan Anda harus berupa composable. Anda dapat melacak permintaan fitur pada Issue Tracker ini.

Animasi transisi

Mulai dari Navigation 2.7.0-alpha01, dukungan untuk menyetel transisi kustom, yang sebelumnya dari AnimatedNavHost, kini didukung langsung di NavHost. Baca catatan rilis untuk informasi selengkapnya.

Selengkapnya

Untuk informasi selengkapnya tentang bermigrasi ke Navigation Compose, lihat referensi berikut:

  • Codelab Navigation Compose: Pelajari dasar-dasar Navigation Compose dengan codelab interaktif.
  • Kini di repositori Android: Aplikasi Android yang berfungsi sepenuhnya dan dibangun sepenuhnya dengan Kotlin dan Jetpack Compose, yang mengikuti praktik terbaik pengembangan dan desain Android serta menyertakan Navigation Compose.
  • Memigrasikan Sunflower ke Jetpack Compose: Postingan blog yang mendokumentasikan perjalanan migrasi aplikasi contoh Sunflower dari View ke Compose, yang juga mencakup migrasi ke Navigation Compose.
  • Jetnews untuk setiap layar: Postingan blog yang mendokumentasikan pemfaktoran ulang dan migrasi contoh Jetnews untuk mendukung semua layar dengan Jetpack Compose dan Navigation Compose.