Navigation 3 पर माइग्रेट करना

Navigation 3, Jetpack Compose के ऐप्लिकेशन में नेविगेशन की सुविधा को इस्तेमाल करने के तरीके में एक बड़ा बदलाव है. साथ ही, यह Navigation 2 के मुकाबले, आर्किटेक्चर के मामले में ज़्यादा फ़ायदेमंद है.

Wear Compose ऐप्लिकेशन को Navigation 2 से Navigation 3 पर माइग्रेट करने के लिए, आर्किटेक्चर में हुए बदलावों और ज़रूरी चरणों के बारे में जानें.

Navigation 3 के मुख्य फ़ायदे

  • बैक स्टैक पर सीधे तौर पर कंट्रोल: NavBackStack असल में, NavKey ऑब्जेक्ट की एक ऐसी सूची होती है जिसमें बदलाव किया जा सकता है. यह सूची, उन स्क्रीन के इतिहास को दिखाती है जिन पर उपयोगकर्ता जा चुका है. इस पर ठीक उसी तरह कंट्रोल किया जाता है जैसे Kotlin के किसी MutableList (add, removeLast, clear) पर किया जाता है. नेविगेशन से जुड़ी कार्रवाइयां करने के लिए, सूची में सीधे तौर पर बदलाव किया जाता है. जैसे, आगे बढ़ने के लिए कोई कुंजी जोड़ना या पीछे जाने के लिए कोई कुंजी हटाना.
  • Compose-First डिज़ाइन: बैक स्टैक को, स्टैंडर्ड ऑब्ज़र्वेबल स्टेट के तौर पर मॉडल किया जाता है. अपने नेविगेशन इतिहास में बदलाव करने पर, ठीक उसी तरह का व्यवहार होता है जैसे Compose की किसी अन्य स्टेट को अपडेट करने पर होता है. इससे, मौजूदा स्क्रीन को दिखाने के लिए, कंपोज़िशन अपने-आप ट्रिगर हो जाता है.
  • डिफ़ॉल्ट रूप से टाइप-सेफ़: स्ट्रिंग पर आधारित रूट पूरी तरह से हटा दिए गए हैं. नेविगेशन में, क्रम से लगाए जा सकने वाले डेटा ऑब्जेक्ट और डेटा क्लास का इस्तेमाल किया जाता है.
  • डिकपल किए गए प्रज़ेंटेशन (सीन की रणनीतियां): यूज़र इंटरफ़ेस (यूआई) ट्रांज़िशन लेयर (NavDisplay और SwipeDismissableSceneStrategy) को, स्टेट ट्रैकिंग (NavBackStack) से पूरी तरह अलग कर दिया गया है. इससे, Wear OS के बिल्ट-इन नेविगेशन ट्रांज़िशन को आसानी से इंटिग्रेट किया जा सकता है.

माइग्रेट करने का तरीका

1. डिपेंडेंसी अपडेट करें

androidx.wear.compose:compose-navigation की पुरानी डिपेंडेंसी हटाएं और Navigation 3 की नई, अलग-अलग डिपेंडेंसी जोड़ें. साथ ही, Kotlin के क्रम से लगाने की सुविधा के लिए सहायता भी जोड़ें.

हटाएं:

implementation("androidx.wear.compose:compose-navigation:...")

जोड़ें:

implementation("androidx.navigation3:navigation3-runtime:...") // State logic
implementation("androidx.navigation3:navigation3-ui:...")      // Display logic
implementation("androidx.wear.compose:compose-navigation3:...") // Wear gestures
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:...") // Requires compiler plugin

2. NavKey लागू करने के लिए, डेस्टिनेशन अपडेट करें

Navigation 2 में, रूटिंग के लिए स्ट्रिंग या सामान्य ऑब्जेक्ट का इस्तेमाल किया जा सकता है. Navigation 3 में, आपको ज़रूर NavKey मार्कर इंटरफ़ेस लागू करना होगा और हर स्क्रीन ऑब्जेक्ट को @Serializable के साथ एनोटेट करना होगा.

यह क्यों ज़रूरी है? यह पक्का करने के लिए कि प्रोसेस खत्म होने पर भी बैक स्टैक को सेव और रीस्टोर किया जा सके, अंडरलाइंग navigation3-runtime स्टेट को क्रम से लगाने के लिए kotlinx-serialization पर निर्भर करता है.

इससे पहले (Navigation 2 - सामान्य टाइप-सेफ़ रूट):

sealed class Nav2Screen {
    data object Landing : Nav2Screen()
    data object List : Nav2Screen()
}

इसके बाद (Navigation 3 - NavKey + क्रम से लगाया जा सकने वाला):

@Serializable
sealed interface MigrationScreen : NavKey {
    @Serializable
    data object Landing : MigrationScreen

    @Serializable
    data object List : MigrationScreen
}

3. रूटिंग लॉजिक बदलें (NavController से NavBackStack)

आपके NavController को, rememberNavBackStack की मदद से शुरू किए गए NavBackStack से बदलें. आपको Wear OS के लिए, खास तौर पर SwipeDismissableSceneStrategy को इंस्टैंशिएट भी करना होगा.

इससे पहले (Navigation 2):

val navController = rememberSwipeDismissableNavController()

इसके बाद (Navigation 3):

val backStack = rememberNavBackStack(MigrationScreen.Landing as NavKey)
val strategy = rememberSwipeDismissableSceneStrategy<NavKey>()

4. NavHost को NavDisplay और entryProvider DSL से बदलें

NavHost कंटेनर और उसके इंटरनल composable("route") { ... } बिल्डर DSL को, NavDisplay और entryProvider { entry<Key> { ... } } DSL से बदल दिया गया है.

इससे पहले (Navigation 2):

SwipeDismissableNavHost(navController = navController, startDestination = "menu") {
    composable("menu") {
        GreetingScreen(
            onShowList = { navController.navigate("list") }
        )
    }
    composable("list") {
        ListScreen()
    }
}

इसके बाद (Navigation 3):

NavDisplay(
    backStack = backStack,
    sceneStrategies = listOf(strategy),
    entryProvider = entryProvider {
        entry<MigrationScreen.Landing> {
            GreetingScreen(
                onShowList = { backStack.add(MigrationScreen.List) }
            )
        }
        entry<MigrationScreen.List> {
            ListScreen()
        }
    }
)