Membuat kode navigasi modular

Halaman ini adalah panduan untuk memodularisasi kode navigasi Anda. Tujuannya adalah untuk melengkapi panduan umum modularisasi aplikasi.

Ringkasan

Modularisasi kode navigasi adalah proses pemisahan kunci navigasi terkait, dan konten yang diwakilinya, ke dalam modul terpisah. Hal ini memberikan pemisahan tanggung jawab yang jelas dan memungkinkan Anda berpindah antar-fitur yang berbeda di aplikasi.

Untuk memodularisasi kode navigasi Anda, lakukan hal berikut:

  • Buat dua submodule: api dan impl untuk setiap fitur di aplikasi Anda
  • Tempatkan tombol navigasi untuk setiap fitur ke dalam modul api-nya
  • Tempatkan entryProviders dan konten yang dapat dijelajahi untuk setiap fitur ke dalam modul impl terkait
  • Sediakan entryProviders ke modul aplikasi utama Anda, baik secara langsung maupun menggunakan injeksi dependensi

Memisahkan fitur ke dalam submodul API dan implementasi

Untuk setiap fitur di aplikasi Anda, buat dua submodule bernama api dan impl (singkatan dari "implementasi"). Gunakan tabel berikut untuk memutuskan tempat menempatkan kode navigasi.

Nama modul

Berisi

api

tombol navigasi

impl

Konten untuk fitur tersebut, termasuk definisi untuk NavEntrys dan entryProvider. Lihat juga menyelesaikan kunci ke konten.

Pendekatan ini memungkinkan satu fitur menavigasi ke fitur lain dengan mengizinkan kontennya, yang ada dalam modul impl, bergantung pada tombol navigasi modul lain, yang ada dalam modul api modul tersebut.

Diagram dependensi modul fitur yang menunjukkan cara modul `impl` dapat bergantung pada modul `api`.
Gambar 1. Diagram dependensi modul fitur yang menunjukkan cara modul implementasi dapat bergantung pada modul API.

Memisahkan entri navigasi menggunakan fungsi ekstensi

Di Navigation 3, konten yang dapat dijelajahi ditentukan menggunakan entri navigasi. Untuk memisahkan entri ini ke dalam modul terpisah, buat fungsi ekstensi di EntryProviderScope dan pindahkan ke modul impl untuk fitur tersebut. Fitur ini dikenal sebagai pembuat entri.

Contoh kode berikut menunjukkan pembuat entri yang membuat dua entri navigasi.

// import androidx.navigation3.runtime.EntryProviderScope
// import androidx.navigation3.runtime.NavKey

fun EntryProviderScope<NavKey>.featureAEntryBuilder() {
    entry<KeyA> {
        ContentRed("Screen A") {
            // Content for screen A
        }
    }
    entry<KeyA2> {
        ContentGreen("Screen A2") {
            // Content for screen A2
        }
    }
}

Panggil fungsi tersebut menggunakan DSL entryProvider saat menentukan entryProvider di modul aplikasi utama.

// import androidx.navigation3.runtime.entryProvider
// import androidx.navigation3.ui.NavDisplay
NavDisplay(
    entryProvider = entryProvider {
        featureAEntryBuilder()
    },
    // ...
)

Menggunakan injeksi dependensi untuk menambahkan entri ke aplikasi utama

Dalam contoh kode sebelumnya, setiap pembuat entri dipanggil langsung oleh aplikasi utama menggunakan DSL entryProvider. Jika aplikasi Anda memiliki banyak layar atau modul fitur, hal ini mungkin tidak dapat diskalakan dengan baik.

Untuk mengatasinya, buat setiap modul fitur memberikan builder entri ke aktivitas aplikasi menggunakan injeksi dependensi.

Misalnya, kode berikut menggunakan multi-binding Dagger, khususnya @IntoSet, untuk menyuntikkan builder entri ke Set yang dimiliki oleh MainActivity. Kemudian, fungsi ini dipanggil secara iteratif di dalam entryProvider, sehingga tidak perlu memanggil banyak fungsi builder entri secara eksplisit.

Modul fitur

// import dagger.Module
// import dagger.Provides
// import dagger.hilt.InstallIn
// import dagger.hilt.android.components.ActivityRetainedComponent
// import dagger.multibindings.IntoSet

@Module
@InstallIn(ActivityRetainedComponent::class)
object FeatureAModule {

    @IntoSet
    @Provides
    fun provideFeatureAEntryBuilder() : EntryProviderScope<NavKey>.() -> Unit = {
        featureAEntryBuilder()
    }
}

Modul aplikasi

// import android.os.Bundle
// import androidx.activity.ComponentActivity
// import androidx.activity.compose.setContent
// import androidx.navigation3.runtime.EntryProviderScope
// import androidx.navigation3.runtime.NavKey
// import androidx.navigation3.runtime.entryProvider
// import androidx.navigation3.ui.NavDisplay
// import javax.inject.Inject

class MainActivity : ComponentActivity() {

    @Inject
    lateinit var entryBuilders: Set<@JvmSuppressWildcards EntryProviderScope<NavKey>.() -> Unit>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NavDisplay(
                entryProvider = entryProvider {
                    entryBuilders.forEach { builder -> this.builder() }
                },
                // ...
            )
        }
    }
}

Jika entri navigasi Anda perlu menavigasi—misalnya, berisi elemen UI yang menavigasi ke layar baru—suntikkan objek yang dapat mengubah status navigasi aplikasi ke setiap fungsi builder.

Referensi

Untuk contoh kode yang menunjukkan cara memodularisasi kode Navigation 3, lihat: