Library Navigator Dinamis memperluas fungsi komponen Navigasi Jetpack untuk berfungsi dengan tujuan yang ditentukan dalam modul fitur. Library ini juga menyediakan penginstalan modul fitur on-demand tanpa hambatan saat menavigasi ke tujuan ini.
Penyiapan
Untuk mendukung modul fitur, gunakan dependensi berikut dalam file build.gradle
modul aplikasi Anda:
Groovy
dependencies { def nav_version = "2.8.4" api "androidx.navigation:navigation-fragment-ktx:$nav_version" api "androidx.navigation:navigation-ui-ktx:$nav_version" api "androidx.navigation:navigation-dynamic-features-fragment:$nav_version" }
Kotlin
dependencies { val nav_version = "2.8.4" api("androidx.navigation:navigation-fragment-ktx:$nav_version") api("androidx.navigation:navigation-ui-ktx:$nav_version") api("androidx.navigation:navigation-dynamic-features-fragment:$nav_version") }
Perhatikan bahwa dependensi Navigasi lainnya harus menggunakan konfigurasi api agar tersedia untuk modul fitur Anda.
Penggunaan dasar
Untuk mendukung modul fitur, ubah semua instance
NavHostFragment
di aplikasi ke
androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment
terlebih dahulu:
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment"
app:navGraph="@navigation/nav_graph"
... />
Selanjutnya, tambahkan atribut app:moduleName
ke tujuan <activity>
, <fragment>
, atau
<navigation>
dalam grafik navigasi modul com.android.dynamic-feature
yang terkait dengan DynamicNavHostFragment
.
Atribut ini memberi tahu library Navigator Dinamis bahwa tujuan
dimiliki oleh modul fitur dengan nama yang Anda
tentukan.
<fragment
app:moduleName="myDynamicFeature"
android:id="@+id/featureFragment"
android:name="com.google.android.samples.feature.FeatureFragment"
... />
Saat Anda menavigasi ke salah satu tujuan tersebut, library Navigator Dinamis akan memeriksa terlebih dahulu apakah modul fitur telah diinstal. Jika modul fitur sudah ada, aplikasi Anda akan menavigasi ke tujuan seperti yang diharapkan. Jika modul tidak ada, aplikasi Anda akan menampilkan tujuan fragmen progres menengah saat menginstal modul. Implementasi default fragmen progres menampilkan UI dasar dengan status progres dan menangani error penginstalan.
Untuk menyesuaikan UI ini, atau untuk menangani progres penginstalan secara manual dari dalam layar aplikasi Anda, lihat bagian Menyesuaikan fragmen progres dan Memantau status permintaan dalam topik ini.
Tujuan yang tidak menentukan app:moduleName
tetap berfungsi tanpa
perubahan dan berperilaku seolah-olah aplikasi Anda menggunakan NavHostFragment
reguler.
Menyesuaikan fragmen progres
Anda dapat mengganti implementasi fragmen progres untuk setiap grafik navigasi
dengan menyetel atribut app:progressDestination
ke ID tujuan
yang ingin Anda gunakan untuk menangani progres penginstalan. Tujuan progres khusus Anda
harus berupa
Fragment
yang berasal dari
AbstractProgressFragment
.
Anda harus mengganti metode abstrak untuk notifikasi tentang progres
penginstalan, error, dan peristiwa lainnya. Anda dapat menampilkan progres penginstalan di
UI pilihan Anda.
Class
DefaultProgressFragment
penerapan default menggunakan API ini untuk menampilkan progres penginstalan.
Memantau status permintaan
Library Navigator Dinamis memungkinkan Anda menerapkan alur UX yang serupa dengan yang ada di Praktik terbaik UX untuk pengiriman on demand, di mana pengguna tetap dalam konteks layar sebelumnya selagi menunggu penginstalan selesai. Dengan cara ini, Anda tidak perlu menampilkan UI menengah atau fragmen progres sama sekali.
Dalam skenario ini, Anda bertanggung jawab untuk memantau dan menangani semua status penginstalan, perubahan progres, error, dan sebagainya.
Untuk memulai alur navigasi non-blocking ini, teruskan objek
DynamicExtras
yang berisi
DynamicInstallMonitor
ke
NavController.navigate()
,
seperti yang ditunjukkan dalam contoh berikut:
Kotlin
val navController = ... val installMonitor = DynamicInstallMonitor() navController.navigate( destinationId, null, null, DynamicExtras(installMonitor) )
Java
NavController navController = ... DynamicInstallMonitor installMonitor = new DynamicInstallMonitor(); navController.navigate( destinationId, null, null, new DynamicExtras(installMonitor); )
Setelah memanggil navigate()
, Anda harus memeriksa nilai
installMonitor.isInstallRequired
untuk melihat apakah navigasi yang dicoba menghasilkan
penginstalan modul fitur.
- Jika nilainya
false
, Anda akan menavigasi ke tujuan normal dan tidak perlu melakukan apa pun. Jika nilainya adalah
true
, Anda harus mulai mengamati objekLiveData
yang sekarang berada diinstallMonitor.status
. ObjekLiveData
ini memberikan updateSplitInstallSessionState
dari library Play Core. Update ini berisi peristiwa progres penginstalan yang dapat Anda gunakan untuk mengupdate UI. Ingatlah untuk menangani semua status terkait seperti yang diuraikan dalam panduan Play Core, termasuk meminta konfirmasi pengguna jika diperlukan.Kotlin
val navController = ... val installMonitor = DynamicInstallMonitor() navController.navigate( destinationId, null, null, DynamicExtras(installMonitor) ) if (installMonitor.isInstallRequired) { installMonitor.status.observe(this, object : Observer<SplitInstallSessionState> { override fun onChanged(sessionState: SplitInstallSessionState) { when (sessionState.status()) { SplitInstallSessionStatus.INSTALLED -> { // Call navigate again here or after user taps again in the UI: // navController.navigate(destinationId, destinationArgs, null, null) } SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION -> { SplitInstallManager.startConfirmationDialogForResult(...) } // Handle all remaining states: SplitInstallSessionStatus.FAILED -> {} SplitInstallSessionStatus.CANCELED -> {} } if (sessionState.hasTerminalStatus()) { installMonitor.status.removeObserver(this); } } }); }
Java
NavController navController = ... DynamicInstallMonitor installMonitor = new DynamicInstallMonitor(); navController.navigate( destinationId, null, null, new DynamicExtras(installMonitor); ) if (installMonitor.isInstallRequired()) { installMonitor.getStatus().observe(this, new Observer<SplitInstallSessionState>() { @Override public void onChanged(SplitInstallSessionState sessionState) { switch (sessionState.status()) { case SplitInstallSessionStatus.INSTALLED: // Call navigate again here or after user taps again in the UI: // navController.navigate(mDestinationId, mDestinationArgs, null, null); break; case SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION: SplitInstallManager.startConfirmationDialogForResult(...) break; // Handle all remaining states: case SplitInstallSessionStatus.FAILED: break; case SplitInstallSessionStatus.CANCELED: break; } if (sessionState.hasTerminalStatus()) { installMonitor.getStatus().removeObserver(this); } } }); }
Setelah penginstalan selesai, objek LiveData
akan menghasilkan
status SplitInstallSessionStatus.INSTALLED
. Kemudian Anda harus memanggil
NavController.navigate()
lagi. Karena modul telah terinstal, panggilan
sekarang akan berhasil berjalan dan aplikasi akan menavigasi ke tujuan seperti yang diharapkan.
Setelah mencapai status terminal, seperti saat penginstalan selesai atau saat
penginstalan gagal, Anda harus menghapus LiveData
observer untuk menghindari kebocoran
memori. Anda dapat memeriksa apakah status mewakili status terminal dengan menggunakan
SplitInstallSessionStatus.hasTerminalStatus()
.
Lihat AbstractProgressFragment
untuk contoh penerapan pengamat ini.
Grafik yang disertakan
Library Navigator Dinamis mendukung penyertaan grafik yang ditentukan dalam modul fitur. Untuk menyertakan grafik yang ditentukan dalam modul fitur, lakukan hal berikut:
Gunakan
<include-dynamic/>
, bukan<include/>
, seperti yang ditunjukkan pada contoh berikut:<include-dynamic android:id="@+id/includedGraph" app:moduleName="includedgraphfeature" app:graphResName="included_feature_nav" app:graphPackage="com.google.android.samples.dynamic_navigator.included_graph_feature" />
Di dalam
<include-dynamic ... />
, Anda harus menentukan atribut berikut:app:graphResName
: nama file resource grafik navigasi. Nama diambil dari nama file grafik. Misalnya, jika grafik menggunakanres/navigation/nav_graph.xml
, nama resource-nya adalahnav_graph
.android:id
- ID tujuan grafik. Library Navigator Dinamis mengabaikan nilaiandroid:id
mana pun yang ditemukan dalam elemen root grafik yang disertakan.app:moduleName
: nama paket modul.
Menggunakan graphPackage yang benar
Penting untuk memastikan bahwa app:graphPackage
benar karena komponen
Navigasi tidak akan dapat menyertakan navGraph
yang ditentukan dari modul
fitur.
Nama paket modul fitur dinamis dikonstruksi dengan menambahkan
nama modul ke applicationId
modul aplikasi dasar. Jadi, jika
modul aplikasi dasar memiliki applicationId
dari com.example.dynamicfeatureapp
dan
modul fitur dinamis bernama DynamicFeatureModule
, maka nama
paket modul dinamis akan menjadi
com.example.dynamicfeatureapp.DynamicFeatureModule
. Nama paket ini
peka terhadap huruf besar/kecil.
Jika ragu, Anda dapat memastikan nama paket modul fitur
dengan memeriksa AndroidManifest.xml
yang dihasilkan. Setelah mem-build project, buka
<DynamicFeatureModule>/build/intermediates/merged_manifest/debug/AndroidManifest.xml
,
yang akan terlihat seperti berikut:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:dist="http://schemas.android.com/apk/distribution" featureSplit="DynamicFeatureModule" package="com.example.dynamicfeatureapp" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" /> <dist:module dist:instant="false" dist:title="@string/title_dynamicfeaturemodule" > <dist:delivery> <dist:install-time /> </dist:delivery> <dist:fusing dist:include="true" /> </dist:module> <application /> </manifest>
Nilai featureSplit
harus cocok dengan nama modul fitur dinamis, dan paket akan cocok dengan applicationId
modul aplikasi dasar. app:graphPackage
adalah kombinasi dari ini: com.example.dynamicfeatureapp.DynamicFeatureModule
.
Menavigasi ke grafik navigasi include-dynamic
Anda hanya dapat menavigasi ke startDestination
grafik navigasi
include-dynamic
. Modul dinamis bertanggung jawab atas grafik navigasinya
sendiri dan aplikasi dasarnya tidak memiliki pengetahuan tentang hal tersebut.
Mekanisme include-dynamic memungkinkan modul aplikasi dasar menyertakan
grafik navigasi bertingkat
yang ditentukan dalam modul dinamis. Grafik navigasi bertingkat ini berperilaku
seperti grafik navigasi bertingkat lainnya. Grafik navigasi root (yaitu, induk
grafik bertingkat) hanya dapat menentukan grafik navigasi bertingkat itu sendiri sebagai
tujuan dan bukan turunannya. Dengan demikian, startDestination
digunakan saat
grafik navigasi include-dynamicnavigation menjadi tujuan.
Batasan
- Grafik yang disertakan secara dinamis saat ini tidak mendukung deep link.
- Grafik bertingkat yang dimuat secara dinamis (yaitu, elemen
<navigation>
denganapp:moduleName
) saat ini tidak mendukung deep link.