Android से जुड़ी स्किल
GitHub पर देखेंJetpack Navigation 3
android skills add navigation-3अपने ऐप्लिकेशन को Navigation 2 से Navigation 3 पर माइग्रेट करने के लिए, यह तरीका अपनाएं:
- Navigation 3 की डिपेंडेंसी जोड़ें.
NavKeyइंटरफ़ेस को लागू करने के लिए, नेविगेशन रूट अपडेट करें.- नेविगेशन की स्थिति को सेव करने और उसमें बदलाव करने के लिए क्लास बनाएं.
NavControllerकी जगह इन क्लास को जोड़ें.- अपनी मंज़िलों को
NavHostकेNavGraphसेentryProviderमें ले जाएं. NavHostकोNavDisplayसे बदलें.- Navigation 2 की डिपेंडेंसी हटाएं.
तैयारी
यहां दिए गए सेक्शन में, माइग्रेशन के लिए ज़रूरी शर्तें और आपके प्रोजेक्ट के बारे में अनुमानों के बारे में बताया गया है. इनमें, माइग्रेशन के लिए काम करने वाली सुविधाओं के साथ-साथ, काम न करने वाली सुविधाओं के बारे में भी बताया गया है.
ज़रूरी शर्तें
- आपको 36 या इसके बाद के वर्शन वाले
compileSdkका इस्तेमाल करना होगा. - आपको नेविगेशन से जुड़े शब्दों के बारे में जानकारी होनी चाहिए.
- डेस्टिनेशन, कंपोज़ेबल फ़ंक्शन होते हैं. Navigation 3 को खास तौर पर Compose के लिए डिज़ाइन किया गया है. Compose में फ़्रैगमेंट और व्यू इस्तेमाल करने के बारे में जानने के लिए, Compose में व्यू इस्तेमाल करना लेख पढ़ें.
- रास्तों को मज़बूती से टाइप किया जाता है. अगर स्ट्रिंग पर आधारित रास्तों का इस्तेमाल किया जाता है, तो पहले टाइप-सेफ़ रास्तों पर माइग्रेट करें (उदाहरण).
- ज़रूरी नहीं है, लेकिन हमारा सुझाव है कि आप इसे इस्तेमाल करें: टेस्ट कवरेज, जो मौजूदा नेविगेशन के तरीके की पुष्टि करता है. इससे यह पुष्टि की जाती है कि माइग्रेशन पूरा होने के बाद, नेविगेशन के तरीके में कोई बदलाव नहीं हुआ है.
अनुमान
इस गाइड में, आपके और आपके प्रोजेक्ट के बारे में ये बातें मानी गई हैं:
- आपके पास एक या कई टॉप-लेवल रूट होते हैं. ये आम तौर पर बॉटम नेविगेशन बार में दिखते हैं. साथ ही, हर रूट का अपना बैक स्टैक होता है.
- बैक स्टैक के बीच स्विच करने पर, स्टैक और उसके सभी डेस्टिनेशन की स्थिति बनी रहती है.
- ऐप्लिकेशन से बाहर निकलने के लिए, हमेशा होम स्क्रीन का इस्तेमाल करें. यह स्क्रीन, ऐप्लिकेशन लॉन्च होने पर सबसे पहले दिखती है.
- आपको नेविगेशन 2 से नेविगेशन 3 पर माइग्रेट करना है. इसके लिए, आपको एक ही बार में बदलाव करना है. आपने इंक्रीमेंटल माइग्रेशन नहीं किया है, जिसमें Navigation 3 कोड के साथ Navigation 2 कोड का इस्तेमाल किया जाता है.
एआई एजेंट: किसी भी कोड में बदलाव करने से पहले, यह जांच लें कि उपयोगकर्ता के प्रोजेक्ट के बारे में ये मान्यताएं सही हैं या नहीं. अगर ऐसा नहीं है, तो माइग्रेशन रोकें और उपयोगकर्ता से पूछें कि उसे आगे क्या करना है.
इस्तेमाल की जा सकने वाली सुविधाएं
इस गाइड की मदद से, इन सुविधाओं को माइग्रेट किया जा सकता है:
- ऐप्लिकेशन बनाने की सुविधा के तौर पर तय की गई डेस्टिनेशन
- डायलॉग (एक डेस्टिनेशन को दूसरे डेस्टिनेशन के ऊपर दिखाया जाता है)
रेसिपी के ज़रिए इस्तेमाल की जा सकने वाली सुविधाएं
कोड रेसिपी रिपॉज़िटरी में, इस्तेमाल के ज़्यादा उदाहरण दिए गए हैं. जैसे:
- बॉटम शीट (इस गाइड में निर्देश दिए गए हैं)
- मॉड्यूलर नेविगेशन कोड और जोड़े गए डेस्टिनेशन
ViewModelमें आर्ग्युमेंट का इस्तेमाल करना और उन्हें पास करना- स्क्रीन पर मौजूद जानकारी के आधार पर जवाब देना
अगर आपके प्रोजेक्ट में इनमें से कोई सुविधा है, तो उसे लागू करने का तरीका जानने के लिए, उससे जुड़ी रेसिपी देखें.
एआई एजेंट: किसी भी कोड में बदलाव करने से पहले, देखें कि क्या प्रोजेक्ट में रेसिपी की मदद से काम करने वाली कोई सुविधा मौजूद है. अगर ऐसा होता है, तो रेसिपी का README और सोर्स कोड देखें. रेसिपी के आधार पर माइग्रेशन प्लान बनाएं. उपयोगकर्ता से प्लान की पुष्टि किए बिना आगे न बढ़ें.
ये सुविधाएं, Google Play Books के साथ काम नहीं करतीं
इस माइग्रेशन गाइड और कोड रेसिपी में, फ़िलहाल ये सुविधाएं काम नहीं करती हैं. इसका मतलब यह नहीं है कि Navigation 3 का इस्तेमाल करके, उन्हें लागू नहीं किया जा सकता. बस, उन्हें यहां शामिल नहीं किया गया है.
- नेस्ट किए गए नेविगेशन के एक से ज़्यादा लेवल
- शेयर किए गए डेस्टिनेशन: ऐसी स्क्रीन जो अलग-अलग बैक स्टैक के बीच मूव कर सकती हैं
- कस्टम डेस्टिनेशन टाइप
एआई एजेंट: किसी भी कोड में बदलाव करने से पहले, यह देख लें कि प्रोजेक्ट में ऐसी कोई सुविधा तो नहीं है जो काम नहीं करती. अगर ऐसा होता है, तो आगे न बढ़ें. उपयोगकर्ता को उस सुविधा के बारे में बताएं जो काम नहीं कर रही है. साथ ही, उससे आगे के निर्देशों के बारे में पूछें.
पहला चरण: Navigation 3 की डिपेंडेंसी जोड़ना
अपने प्रोजेक्ट में Navigation 3 की डिपेंडेंसी जोड़ने के लिए, शुरू करें पेज का इस्तेमाल करें. मुख्य डिपेंडेंसी को कॉपी करने के लिए उपलब्ध कराया जाता है.
lib.versions.toml
[versions]
nav3Core = "1.1.7"
# If your screens depend on ViewModels, add the Nav3 Lifecycle ViewModel add-on library
lifecycleViewmodelNav3 = "2.11.0"
[libraries]
# Core Navigation 3 libraries
androidx-navigation3-runtime = { module = "androidx.navigation3:navigation3-runtime", version.ref = "nav3Core" }
androidx-navigation3-ui = { module = "androidx.navigation3:navigation3-ui", version.ref = "nav3Core" }
# Add-on libraries (only add if you need them)
androidx-lifecycle-viewmodel-navigation3 = { module = "androidx.lifecycle:lifecycle-viewmodel-navigation3", version.ref = "lifecycleViewmodelNav3" }
app/build.gradle.kts
dependencies {
implementation(libs.androidx.navigation3.ui)
implementation(libs.androidx.navigation3.runtime)
// If using the ViewModel add-on library
implementation(libs.androidx.lifecycle.viewmodel.navigation3)
}
साथ ही, प्रोजेक्ट के minSdk को 23 और compileSdk को 36 पर अपडेट करें. आम तौर पर, ये app/build.gradle.kts या lib.versions.toml में दिखते हैं.
दूसरा चरण: NavKey इंटरफ़ेस लागू करने के लिए, नेविगेशन के रास्तों को अपडेट करना
हर नेविगेशन route को अपडेट करें, ताकि वह NavKey
इंटरफ़ेस को लागू कर सके. इससे आपको नेविगेशन की स्थिति सेव करने में मदद पाने के लिए, rememberNavBackStack का इस्तेमाल करने की सुविधा मिलती है.
पहले:
@Serializable data object RouteA
बाद में:
@Serializable data object RouteA : NavKey
तीसरा चरण: नेविगेशन की स्थिति को सेव करने और उसमें बदलाव करने के लिए क्लास बनाना
तीसरे चरण का पहला हिस्सा: नेविगेशन स्टेट होल्डर बनाना
नीचे दिए गए कोड को NavigationState.kt नाम की फ़ाइल में कॉपी करें. अपने प्रोजेक्ट स्ट्रक्चर से मेल खाने वाला पैकेज का नाम जोड़ें.
// package com.example.project import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSerializable import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshots.SnapshotStateList import androidx.compose.runtime.toMutableStateList import androidx.navigation3.runtime.NavBackStack import androidx.navigation3.runtime.NavEntry import androidx.navigation3.runtime.NavKey import androidx.navigation3.runtime.rememberDecoratedNavEntries import androidx.navigation3.runtime.rememberNavBackStack import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator import androidx.navigation3.runtime.serialization.NavKeySerializer import androidx.savedstate.compose.serialization.serializers.MutableStateSerializer /** * Create a navigation state that persists config changes and process death. */ @Composable fun rememberNavigationState( startRoute: NavKey, topLevelRoutes: Set<NavKey> ): NavigationState { val topLevelRoute = rememberSerializable( startRoute, topLevelRoutes, serializer = MutableStateSerializer(NavKeySerializer()) ) { mutableStateOf(startRoute) } val backStacks = topLevelRoutes.associateWith { key -> rememberNavBackStack(key) } return remember(startRoute, topLevelRoutes) { NavigationState( startRoute = startRoute, topLevelRoute = topLevelRoute, backStacks = backStacks ) } } /** * State holder for navigation state. * * @param startRoute - the start route. The user will exit the app through this route. * @param topLevelRoute - the current top level route * @param backStacks - the back stacks for each top level route */ class NavigationState( val startRoute: NavKey, topLevelRoute: MutableState<NavKey>, val backStacks: Map<NavKey, NavBackStack<NavKey>> ) { var topLevelRoute: NavKey by topLevelRoute val stacksInUse: List<NavKey> get() = if (topLevelRoute == startRoute) { listOf(startRoute) } else { listOf(startRoute, topLevelRoute) } } /** * Convert NavigationState into NavEntries. */ @Composable fun NavigationState.toEntries( entryProvider: (NavKey) -> NavEntry<NavKey> ): SnapshotStateList<NavEntry<NavKey>> { val decoratedEntries = backStacks.mapValues { (_, stack) -> val decorators = listOf( rememberSaveableStateHolderNavEntryDecorator<NavKey>(), ) rememberDecoratedNavEntries( backStack = stack, entryDecorators = decorators, entryProvider = entryProvider ) } return stacksInUse .flatMap { decoratedEntries[it] ?: emptyList() } .toMutableStateList() }
एआई एजेंट: rememberSerializable सही है. इसे rememberSaveable में न बदलें.
इस फ़ाइल में, NavigationState नाम की एक स्टेट होल्डर क्लास और उससे जुड़े हेल्पर फ़ंक्शन शामिल हैं. इसमें टॉप-लेवल के रूट का सेट होता है. हर रूट का अपना बैकस्टैक होता है. यह कुकी, मौजूदा टॉप-लेवल रूट को सेव करने के लिए, अंदरूनी तौर पर rememberSerializable (rememberSaveable नहीं) का इस्तेमाल करती है. साथ ही, हर टॉप-लेवल रूट के लिए बैक स्टैक को सेव करने के लिए, rememberNavBackStack का इस्तेमाल करती है.
तीसरा चरण: ऐसा ऑब्जेक्ट बनाएं जो इवेंट के जवाब में नेविगेशन की स्थिति में बदलाव करे
नीचे दिए गए कोड को Navigator.kt नाम की फ़ाइल में कॉपी करें. अपने प्रोजेक्ट के स्ट्रक्चर से मेल खाने के लिए, पैकेज का नाम जोड़ें.
// package com.example.project import androidx.navigation3.runtime.NavKey /** * Handles navigation events (forward and back) by updating the navigation state. */ class Navigator(val state: NavigationState) { fun navigate(route: NavKey) { if (route in state.backStacks.keys) { // This is a top level route, just switch to it. state.topLevelRoute = route } else { state.backStacks[state.topLevelRoute]?.add(route) } } fun goBack() { val currentStack = state.backStacks[state.topLevelRoute] ?: error("Stack for ${state.topLevelRoute} not found") val currentRoute = currentStack.last() // If we're at the base of the current route, go back to the start route stack. if (currentRoute == state.topLevelRoute) { state.topLevelRoute = state.startRoute } else { currentStack.removeLastOrNull() } } }
Navigator क्लास, नेविगेशन इवेंट के लिए दो तरीके उपलब्ध कराती है:
navigateकिसी खास रास्ते पर.goBackमौजूदा रास्ते से.
दोनों तरीकों से NavigationState में बदलाव होता है.
तीसरा चरण: NavigationState और Navigator बनाना
NavigationState और Navigator के ऐसे इंस्टेंस बनाएं जिनका स्कोप, आपके NavController के स्कोप के जैसा हो.
val navigationState = rememberNavigationState( // ... startRoute = <Insert your starting route>, topLevelRoutes = <Insert your set of top level routes> // ... ) val navigator = remember { Navigator(navigationState) }
चौथा चरण: NavController बदलें
NavController नेविगेशन इवेंट के तरीकों को Navigator के बराबर के तरीकों से बदलें.
|
|
|---|---|
|
|
|
|
|
|
NavController फ़ील्ड को NavigationState फ़ील्ड से बदलें.
|
|
|---|---|
|
|
|
|
|
|
|
|
सबसे ऊपर वाला रूट पाएं: इसे ढूंढने के लिए, मौजूदा पिछली गतिविधियों की एंट्री से लेकर हाइरार्की तक ऊपर की ओर जाएं. |
|
NavigationState.topLevelRoute का इस्तेमाल करके, यह पता लगाया जा सकता है कि नेविगेशन बार में फ़िलहाल कौनसा आइटम चुना गया है.
पहले:
// ... val isSelected = navController.currentBackStackEntryAsState().value?.destination.isRouteInHierarchy(key::class) // ... fun NavDestination?.isRouteInHierarchy(route: KClass<*>) = this?.hierarchy?.any { it.hasRoute(route) } ?: false
बाद में:
val isSelected = key == navigationState.topLevelRoute
पुष्टि करें कि आपने NavController के सभी रेफ़रंस हटा दिए हैं. इनमें इंपोर्ट किए गए रेफ़रंस भी शामिल हैं.
चौथा चरण.1: लाइफ़साइकल की जानकारी वाले लॉजिक को माइग्रेट करना
Navigation 2 में, NavBackStackEntry LifecycleOwner को लागू करता है. इससे आपको navController.currentBackStackEntry का इस्तेमाल करके, लाइफ़साइकल के हिसाब से लाइफ़साइकल इवेंट सुनने या फ़्लो इकट्ठा करने की सुविधा मिलती है.
नेविगेशन 3 में, NavDisplay हर डेस्टिनेशन के कंपोज़ेबल कॉन्टेंट को LocalLifecycleOwner.current के ज़रिए, एंट्री-स्कोप वाला LifecycleOwner उपलब्ध कराता है. ज़्यादा जानकारी के लिए, डेस्टिनेशन का लाइफ़साइकल देखें.
आपको अपने डेस्टिनेशन के कंपोज़ेबल कॉन्टेंट में, लाइफ़साइकल के बारे में जानकारी रखने वाली कार्रवाइयां सीधे तौर पर करनी चाहिए. इसके लिए, LocalLifecycleOwner.current को रेफ़रंस के तौर पर इस्तेमाल करें.
उदाहरण के लिए, अगर बैकस्टैक एंट्री का इस्तेमाल करके, लाइफ़साइकल के हिसाब से किसी फ़्लो को इकट्ठा किया जाता है, तो:
पहले:
// In your destination screen or host val lifecycleOwner = navController.currentBackStackEntry!! val state by flow.collectAsStateWithLifecycle(lifecycleOwner = lifecycleOwner)
बाद में:
// Inside the destination composable val state by flow.collectAsStateWithLifecycle()
चौथा चरण.2 नतीजों को पास करने की सुविधा माइग्रेट करना
Navigation 2 में, डेस्टिनेशन ने NavBackStackEntry पर मौजूद SavedStateHandle का इस्तेमाल करके, नतीजों को पिछले डेस्टिनेशन पर वापस भेज दिया. SavedStateHandle को सेव किए गए इंस्टेंस की स्थिति से बैक अप लिया जाता है. इसलिए, प्रोसेस बंद होने के बाद भी लौटाया गया डेटा अपने-आप सेव हो जाता है.
पहले:
// Sender destination: navController.previousBackStackEntry?.savedStateHandle?.set("contact_key", contact) navController.popBackStack() // Receiver destination: val lifecycleOwner = LocalLifecycleOwner.current navController.currentBackStackEntry?.savedStateHandle ?.getLiveData<Contact>("contact_key") ?.observe(lifecycleOwner) { contact -> viewModel.onRecipientSelected(contact) }
नेविगेशन 3 में, अपने NavDisplay.entryDecorators में rememberResultEventBusNavEntryDecorator() जोड़ें. भेजने वाले के डेस्टिनेशन की entryProvider मैपिंग में, LocalResultEventBus.current को वापस पाएं और sendResult() को कॉल करें. डेटा पाने वाले डेस्टिनेशन में, इवेंट को ViewModel पर फ़ॉरवर्ड करने या साइड इफ़ेक्ट ट्रिगर करने के लिए, ResultEffect का इस्तेमाल करें.
बाद में:
// Sender destination (in entryProvider): entry<ContactPickerRoute> { val resultBus = LocalResultEventBus.current ContactPickerScreen( onContactSelected = { contact -> resultBus.sendResult<Contact>(result = contact) navigator.goBack() } ) } // Receiver destination: @Composable fun ComposeMessageScreen(viewModel: ComposeMessageViewModel = viewModel()) { ResultEffect<Contact> { contact -> viewModel.onRecipientSelected(contact) } ComposeMessageContent(recipient = viewModel.recipient) }
राज्य के हिसाब से निगरानी करने के लिए, resultBus.conflateAsState() पर कॉल करें. ज़्यादा जानकारी के लिए, नतीजे दिखाना लेख पढ़ें.
पांचवां चरण: अपने डेस्टिनेशन को NavHost के NavGraph से entryProvider में ले जाना
Navigation 2 में, NavGraphBuilder DSL का इस्तेमाल करके, अपने डेस्टिनेशन तय किए जाते हैं. आम तौर पर, ऐसा NavHost के ट्रेलिंग लैम्डा के अंदर किया जाता है. यहां एक्सटेंशन फ़ंक्शन का इस्तेमाल करना आम बात है. इसके बारे में अपने नेविगेशन कोड को कैप्सूल में बंद करना लेख में बताया गया है.
Navigation 3 में, entryProvider का इस्तेमाल करके डेस्टिनेशन तय किए जाते हैं. यह entryProvider, किसी रास्ते को NavEntry में बदलता है. अहम जानकारी: entryProvider, एंट्री के बीच पैरंट-चाइल्ड रिलेशनशिप तय नहीं करता.
इस माइग्रेशन गाइड में, पैरंट-चाइल्ड रिलेशनशिप को इस तरह से मॉडल किया गया है:
NavigationStateमें टॉप-लेवल के रास्तों (पैरंट रास्तों) का एक सेट होता है और हर रास्ते के लिए एक स्टैक होता है. यह कुकी, मौजूदा टॉप-लेवल रूट और उससे जुड़े स्टैक को ट्रैक करती है.- किसी नए रास्ते पर नेविगेट करते समय,
Navigatorयह देखता है कि रास्ता टॉप-लेवल का है या नहीं. अगर ऐसा है, तो मौजूदा टॉप-लेवल रूट और स्टैक अपडेट हो जाते हैं. अगर ऐसा नहीं है, तो यह बच्चे के लिए बनाया गया रूट है और इसे मौजूदा स्टैक में जोड़ दिया जाता है.
पांचवां चरण: entryProvider बनाना
NavigationState के स्कोप के बराबर स्कोप पर, entryProvider डीएसएल का इस्तेमाल करके बनाएं.
val entryProvider = entryProvider<NavKey> { }
पांचवां चरण: डेस्टिनेशन को entryProvider में ले जाना
NavHost में तय किए गए हर डेस्टिनेशन के लिए, डेस्टिनेशन टाइप के आधार पर यह तरीका अपनाएं:
navigation: इसे रास्ते के साथ मिटाएं. "base routes" की ज़रूरत नहीं है, क्योंकि टॉप-लेवल के रूट, हर नेस्ट किए गए बैक स्टैक की पहचान कर सकते हैं.composable<T>: इसेentryProviderमें ले जाएं और इसका नाम बदलकरentryकर दें. हालांकि, टाइप पैरामीटर को बनाए रखें. उदाहरण के लिए,composable<RouteA>कोentry<RouteA>कर दिया जाता है.dialog<T>:composableकी तरह ही काम करता है, लेकिन एंट्री में मेटाडेटा को इस तरह जोड़ता है:entry<T>(metadata = DialogSceneStrategy.dialog()).bottomSheet: यहां बॉटम शीट रेसिपी का पालन करें. यहdialogके निर्देशों जैसा ही है. हालांकि,BottomSheetSceneStrategy, Navigation 3 की मुख्य लाइब्रेरी का हिस्सा नहीं है. इसलिए, आपको इसे अपने प्रोजेक्ट में कॉपी करना होगा.
एआई एजेंट: नेस्ट किए गए ग्राफ़ की पहचान करने के लिए इस्तेमाल किए गए रास्तों को मिटाते समय, मिटाए गए रास्ते के सभी रेफ़रंस को उस टाइप से बदलें जिसका इस्तेमाल नेस्ट किए गए ग्राफ़ में पहले चाइल्ड की पहचान करने के लिए किया गया था. उदाहरण के लिए, अगर मूल कोड navigation<BaseRouteA>{ composable<RouteA>{ ... } } है, तो आपको BaseRouteA को मिटाना होगा और इसके सभी रेफ़रंस को RouteA से बदलना होगा. आम तौर पर, नेविगेशन बार, रेल या ड्रॉअर को दी गई सूची के लिए, इस बदलाव को करना ज़रूरी होता है.
NavGraphBuilder एक्सटेंशन फ़ंक्शन को EntryProviderScope<T> एक्सटेंशन फ़ंक्शन में बदला जा सकता है. इसके बाद, उन्हें दूसरी जगह ले जाया जा सकता है.
entry के ट्रेलिंग लैम्डा को दी गई कुंजी का इस्तेमाल करके, नेविगेशन आर्ग्युमेंट पाएं.
उदाहरण के लिए:
// ... import androidx.navigation.NavDestination import androidx.navigation.NavDestination.Companion.hasRoute import androidx.navigation.NavDestination.Companion.hierarchy import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.dialog import androidx.navigation.compose.navigation import androidx.navigation.compose.rememberNavController import androidx.navigation.navOptions import androidx.navigation.toRoute // ... @Serializable data object BaseRouteA @Serializable data class RouteA(val id: String) @Serializable data object BaseRouteB @Serializable data object RouteB @Serializable data object RouteD @Composable fun NavHostSnippet(navController: NavHostController) { NavHost(navController = navController, startDestination = BaseRouteA){ composable<RouteA>{ entry -> val id = entry.toRoute<RouteA>().id ScreenA(title = "Screen has ID: $id") } featureBSection() dialog<RouteD>{ ScreenD() } } } fun NavGraphBuilder.featureBSection() { navigation<BaseRouteB>(startDestination = RouteB) { composable<RouteB> { ScreenB() } } }
बन जाता है:
// ... import androidx.navigation3.runtime.EntryProviderScope import androidx.navigation3.runtime.NavKey import androidx.navigation3.runtime.entryProvider import androidx.navigation3.scene.DialogSceneStrategy // ... @Serializable data class RouteA(val id: String) : NavKey @Serializable data object RouteB : NavKey @Serializable data object RouteD : NavKey val entryProvider = entryProvider { entry<RouteA>{ key -> ScreenA(title = "Screen has ID: ${key.id}") } featureBSection() entry<RouteD>(metadata = DialogSceneStrategy.dialog()){ ScreenD() } } fun EntryProviderScope<NavKey>.featureBSection() { entry<RouteB> { ScreenB() } }
छठा चरण: NavHost को NavDisplay से बदलें
NavHost को NavDisplay से बदलें.
NavHostको मिटाकर उसकी जगहNavDisplayजोड़ें.entries = navigationState.toEntries(entryProvider)को पैरामीटर के तौर पर तय करें. यह नेविगेशन की स्थिति को उन एंट्री में बदलता है जिन्हेंNavDisplay,entryProviderका इस्तेमाल करके दिखाता है.NavDisplay.onBackकोnavigator.goBack()से कनेक्ट करें. इससेNavDisplayके बिल्ट-इन बैक हैंडलर के पूरा होने पर,navigatorनेविगेशन की स्थिति को अपडेट करता है.- अगर आपके पास डायलॉग डेस्टिनेशन हैं, तो
NavDisplayकेsceneStrategiesपैरामीटर मेंDialogSceneStrategyजोड़ें.
उदाहरण के लिए:
NavDisplay( entries = navigationState.toEntries(entryProvider), onBack = { navigator.goBack() }, sceneStrategies = remember { listOf(DialogSceneStrategy()) } )
सातवां चरण: डीप लिंक माइग्रेट करना
Navigation 2 में, डीप लिंक को सीधे तौर पर नेविगेशन ग्राफ़ में तय किया जाता था. इसके लिए, डेस्टिनेशन के deepLinks पैरामीटर का इस्तेमाल किया जाता था.
Navigation 3 में, डीप लिंक को नेविगेशन यूज़र इंटरफ़ेस (यूआई) से अलग मैनेज किया जाता है. शुरुआती बैक स्टैक बनाने के लिए, अपनी ऐक्टिविटी में DeepLinkMatcher तय करें और आने वाले अनुरोधों का मिलान करें.
पहले:
Navigation 2 में, आपने इस तरह का डीप लिंक तय किया होगा:
composable<RouteA>( deepLinks = listOf( navDeepLink { uriPattern = "www.example.com/user/{id}" } ) ) { // ... }
बाद में:
नेविगेशन 3 में, रूट के लिए UriDeepLinkMatcher तय किया जाता है:
val userMatcher = UriDeepLinkMatcher( DeepLinkUri("www.example.com/user/{id}"), serializer<RouteA>() )
इसके बाद, अपनी ऐक्टिविटी के onCreate (और onNewIntent) में, आने वाले इंटेंट को मैच करें और पिछली ऐक्टिविटी को शुरू करें:
val deepLinkMatchers: List<DeepLinkMatcher<*, *>> = listOf( userMatcher, ) class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val request = DeepLinkRequest(intent = intent) val matchResult = deepLinkMatchers .mapNotNull { it.match(request) } .maxOrNull() val backStack = when (matchResult) { null -> listOf(HomeKey) is BackStackMatchResult<*, *> -> { @Suppress("UNCHECKED_CAST") matchResult.backStack as List<NavKey> } else -> listOf(matchResult.key) } // Use backStack with NavDisplay } }
कस्टम आर्ग्युमेंट टाइप
नेविगेशन 2 में, आपने कस्टम या तीसरे पक्ष के तर्क टाइप (जैसे कि
LocalDateTime) को कस्टम NavType लागू करने और typeMap का इस्तेमाल करके हैंडल किया.
नेविगेशन 3 में, यूआरआई पैरामीटर से कस्टम या तीसरे पक्ष के टाइप को डिसिरियलाइज़ करने के लिए, DeepLinkSerializer को तय करें. ज़्यादा जानकारी के लिए, DeepLinkSerializer की मदद से कस्टम सीरियलाइज़ेशन लेख पढ़ें.
सिंथेटिक बैक स्टैक और कस्टम मैचर्स जैसे ज़्यादा बेहतर इस्तेमाल के उदाहरणों के लिए, डीप लिंक की सुविधा चालू करना गाइड देखें.
आठवां चरण: Navigation 2 की डिपेंडेंसी हटाना
Navigation 2 के सभी इंपोर्ट और लाइब्रेरी डिपेंडेंसी हटाएं.
खास जानकारी
बधाई हो! आपका प्रोजेक्ट अब Navigation 3 पर माइग्रेट हो गया है. अगर आपको या आपके एआई एजेंट को इस गाइड का इस्तेमाल करते समय कोई समस्या आ रही है, तो यहां जाकर बग की शिकायत करें.