नेविगेशन कॉम्पोनेंट के साथ प्रोग्राम के हिसाब से इंटरैक्ट करें

नेविगेशन कॉम्पोनेंट प्रोग्राम के हिसाब से, प्रोजेक्ट बनाने और इंटरैक्ट करने के तरीके उपलब्ध कराता है इस्तेमाल किए जा सकते हैं.

NavHostफ़्रैगमेंट बनाएं

Google Analytics 4 पर माइग्रेट करने के लिए, NavHostFragment.create() प्रोग्राम बनाकर किसी खास ग्राफ़ रिसॉर्स के साथ NavHostFragment बनाना हो, जैसा कि नीचे उदाहरण में दिखाया गया है:

Kotlin

val finalHost = NavHostFragment.create(R.navigation.example_graph)
supportFragmentManager.beginTransaction()
    .replace(R.id.nav_host, finalHost)
    .setPrimaryNavigationFragment(finalHost) // equivalent to app:defaultNavHost="true"
    .commit()

Java

NavHostFragment finalHost = NavHostFragment.create(R.navigation.example_graph);
getSupportFragmentManager().beginTransaction()
    .replace(R.id.nav_host, finalHost)
    .setPrimaryNavigationFragment(finalHost) // equivalent to app:defaultNavHost="true"
    .commit();

ध्यान दें कि setPrimaryNavigationFragment(finalHost) आपका NavHost इंटरसेप्ट सिस्टम के वापस जाने वाले बटन को दबाने पर ऐसा होता है. इस व्यवहार को यहां भी लागू किया जा सकता है: app:defaultNavHost="true" जोड़कर, अपना NavHost एक्सएमएल. अगर आपको पसंद के मुताबिक 'वापस जाएं' बटन का व्यवहार और नहीं चाहते कि आपका NavHost वापस जाएं बटन दबाए, तो आप setPrimaryNavigationFragment() के लिए null.

नेविगेशन 2.2.0 से शुरू करके, आप NavBackStackEntry नेविगेशन स्टैक पर किसी भी डेस्टिनेशन के लिए कॉल करें NavController.getBackStackEntry(), उसे एक डेस्टिनेशन आईडी भेजना. अगर पिछली गतिविधियों में एक से ज़्यादा इंस्टेंस हैं दिए गए डेस्टिनेशन में से, getBackStackEntry() सबसे ऊपर वाला इंस्टेंस लौटाता है से हटा दिया जाएगा.

वापस लौटाए गए NavBackStackEntry से Lifecycle, ViewModelStore और SavedStateRegistry डेस्टिनेशन के लेवल पर. ये ऑब्जेक्ट, पिछली गतिविधियों पर डेस्टिनेशन के लाइफ़टाइम के लिए मान्य हैं. जब संबंधित गंतव्य पॉप-अप होता है पिछली गतिविधियों में शामिल हो जाते हैं, Lifecycle को नष्ट कर दिया जाता है, और स्टेटस अब सेव नहीं किया जाता है. साथ ही, ViewModel ऑब्जेक्ट को हटा दिया जाता है.

ये प्रॉपर्टी आपको ViewModel ऑब्जेक्ट के लिए Lifecycle और स्टोर देती हैं और इन क्लास के साथ काम करती हैं सेव की गई स्थिति, कोई भी आप किस तरह के गंतव्य का उपयोग करते हैं. यह खास तौर पर तब मददगार होता है, जब ऐसे डेस्टिनेशन टाइप जिनमें अपने-आप जुड़ा हुआ Lifecycle नहीं होता, जैसे कि कस्टम डेस्टिनेशन.

उदाहरण के लिए, NavBackStackEntry के Lifecycle को ठीक वैसे ही देखा जा सकता है आपको किसी फ़्रैगमेंट या गतिविधि के Lifecycle दिखेंगे. इसके अलावा, NavBackStackEntry एक LifecycleOwner है. इसका मतलब है कि आप इसका इस्तेमाल तब कर सकते हैं, जब LiveData या लाइफ़साइकल की जानकारी वाले अन्य कॉम्पोनेंट के साथ ऑब्ज़र्विंग की जा रही है, जैसा कि नीचे दिया गया उदाहरण:

Kotlin

myViewModel.liveData.observe(backStackEntry, Observer { myData ->
    // react to live data update
})

Java

myViewModel.getLiveData().observe(backStackEntry, myData -> {
    // react to live data update
});

जब भी navigate() को कॉल किया जाता है, तब लाइफ़साइकल की स्थिति अपने-आप अपडेट हो जाती है. उन डेस्टिनेशन के लिए लाइफ़साइकल स्टेटस जो पिछली गतिविधियों में सबसे ऊपर नहीं हैं अगर गंतव्य अब भीRESUMEDSTARTED FloatingWindow डेस्टिनेशन, जैसे कि डायलॉग डेस्टिनेशन या STOPPED के लिए नहीं तो.

पिछले गंतव्य पर कोई परिणाम वापस करना

नेविगेशन 2.3 और उसके बाद के वर्शन में, NavBackStackEntry SavedStateHandle. SavedStateHandle एक की-वैल्यू मैप होता है, जिसे स्टोर और वापस पाने के लिए इस्तेमाल किया जा सकता है डेटा शामिल है. ये वैल्यू, कॉन्फ़िगरेशन के साथ-साथ प्रोसेस बंद होने के दौरान भी बनी रहती हैं बदलाव करता है और उसी ऑब्जेक्ट के ज़रिए उपलब्ध रहता है. दिए गए डेटा का इस्तेमाल करके SavedStateHandle, एक डेस्टिनेशन से दूसरे डेस्टिनेशन के बीच डेटा को ऐक्सेस और पास किया जा सकता है. यह विशेष रूप से एक ऐसे तरीके के रूप में उपयोगी है, जिसकी मदद से किसी डेस्टिनेशन पर क्लिक करें.

डेटा को डेस्टिनेशन B से डेस्टिनेशन A को वापस भेजने के लिए, पहले डेस्टिनेशन A को सेट अप करें, ताकि वह SavedStateHandle पर नतीजा सुन सके. ऐसा करने के लिए, NavBackStackEntry को getCurrentBackStackEntry() एपीआई और फिर LiveData को observe SavedStateHandle की ओर से उपलब्ध कराया गया.

Kotlin

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    val navController = findNavController();
    // We use a String here, but any type that can be put in a Bundle is supported
    navController.currentBackStackEntry?.savedStateHandle?.getLiveData<String>("key")?.observe(
        viewLifecycleOwner) { result ->
        // Do something with the result.
    }
}

Java

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    NavController navController = NavHostFragment.findNavController(this);
    // We use a String here, but any type that can be put in a Bundle is supported
    MutableLiveData<String> liveData = navController.getCurrentBackStackEntry()
            .getSavedStateHandle()
            .getLiveData("key");
    liveData.observe(getViewLifecycleOwner(), new Observer<String>() {
        @Override
        public void onChanged(String s) {
            // Do something with the result.
        }
    });
}

गंतव्य B में, आपको इसके SavedStateHandle पर परिणाम set करना होगा getPreviousBackStackEntry() एपीआई का इस्तेमाल करके डेस्टिनेशन A.

Kotlin

navController.previousBackStackEntry?.savedStateHandle?.set("key", result)

Java

navController.getPreviousBackStackEntry().getSavedStateHandle().set("key", result);

अगर आपको किसी नतीजे को सिर्फ़ एक बार मैनेज करना है, तो आपको remove() SavedStateHandle पर क्लिक करें. यदि आप परिणाम के रूप में, LiveData किसी भी नए Observer इंस्टेंस.

डायलॉग डेस्टिनेशन का इस्तेमाल करते समय इन बातों का ध्यान रखें

जब आप किसी ऐसे डेस्टिनेशन पर navigate पर जाते हैं जहां NavHost (जैसे कि कोई <fragment> मंज़िल), पिछला गंतव्य इसकी लाइफ़साइकल रुक गई है और LiveData पर किसी भी कॉलबैक को रोका जा सकता है SavedStateHandle की ओर से उपलब्ध कराया गया.

हालांकि, किसी डायलॉग डेस्टिनेशन, स्क्रीन पर पिछला डेस्टिनेशन भी दिख रहा है, इसलिए अब भी दिख रहा है मौजूदा डेस्टिनेशन न होने के बावजूद, STARTED. इसका मतलब है कि लाइफ़साइकल वाले तरीकों में getCurrentBackStackEntry(), जैसे कि onViewCreated(), डायलॉग डेस्टिनेशन का NavBackStackEntry दिखाएगा कॉन्फ़िगरेशन में बदलाव या मौत और मनोरंजन की प्रोसेस के बाद (जब से को दूसरे डेस्टिनेशन के ऊपर वापस लाया जाता है). इसलिए, आपको getBackStackEntry() अपने गंतव्य के आईडी के साथ यह सुनिश्चित करें कि आप हमेशा सही NavBackStackEntry.

इसका मतलब यह भी है कि LiveData के नतीजे पर सेट किया गया कोई भी Observer यह तब भी ट्रिगर होता है, जब डायलॉग डेस्टिनेशन स्क्रीन पर मौजूद होते हैं. अगर आपको परिणाम की जाँच तभी करनी है जब डायलॉग गंतव्य बंद हो और मौजूदा डेस्टिनेशन बन जाता है, तो आपको पता चलेगा कि NavBackStackEntry से जुड़ा Lifecycle और नतीजा फिर से पाएं सिर्फ़ तब, जब यह RESUMED हो जाए.

Kotlin

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val navController = findNavController();
    // After a configuration change or process death, the currentBackStackEntry
    // points to the dialog destination, so you must use getBackStackEntry()
    // with the specific ID of your destination to ensure we always
    // get the right NavBackStackEntry
    val navBackStackEntry = navController.getBackStackEntry(R.id.your_fragment)

    // Create our observer and add it to the NavBackStackEntry's lifecycle
    val observer = LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_RESUME
            && navBackStackEntry.savedStateHandle.contains("key")) {
            val result = navBackStackEntry.savedStateHandle.get<String>("key");
            // Do something with the result
        }
    }
    navBackStackEntry.lifecycle.addObserver(observer)

    // As addObserver() does not automatically remove the observer, we
    // call removeObserver() manually when the view lifecycle is destroyed
    viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_DESTROY) {
            navBackStackEntry.lifecycle.removeObserver(observer)
        }
    })
}

Java

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    NavController navController = NavHostFragment.findNavController(this);
    // After a configuration change or process death, the currentBackStackEntry
    // points to the dialog destination, so you must use getBackStackEntry()
    // with the specific ID of your destination to ensure we always
    // get the right NavBackStackEntry
    final NavBackStackEntry navBackStackEntry = navController.getBackStackEntry(R.id.your_fragment);

    // Create our observer and add it to the NavBackStackEntry's lifecycle
    final LifecycleEventObserver observer = new LifecycleEventObserver() {
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
            if (event.equals(Lifecycle.Event.ON_RESUME)
                && navBackStackEntry.getSavedStateHandle().contains("key")) {
                String result = navBackStackEntry.getSavedStateHandle().get("key");
                // Do something with the result
            }
        }
    };
    navBackStackEntry.getLifecycle().addObserver(observer);

    // As addObserver() does not automatically remove the observer, we
    // call removeObserver() manually when the view lifecycle is destroyed
    getViewLifecycleOwner().getLifecycle().addObserver(new LifecycleEventObserver() {
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
            if (event.equals(Lifecycle.Event.ON_DESTROY)) {
                navBackStackEntry.getLifecycle().removeObserver(observer)
            }
        }
    });
}

नेविगेशन बैक स्टैक में NavBackStackEntry हर डेस्टिनेशन के लिए ही नहीं, बल्कि हर पैरंट नेविगेशन के लिए भी किसी डेस्टिनेशन की जानकारी देने वाला ग्राफ़. इसकी मदद से आपको NavBackStackEntry, जो नेविगेशन ग्राफ़ के दायरे में आता है. नेविगेशन ग्राफ़ के स्कोप वाला NavBackStackEntry, ViewModel को बनाने का तरीका बताता है, जो एक नेविगेशन ग्राफ़ तक सीमित है. इससे आपको अलग-अलग प्लैटफ़ॉर्म के बीच यूज़र इंटरफ़ेस (यूआई) से जुड़ा डेटा शेयर करने में मदद मिलेगी ग्राफ़ के डेस्टिनेशन. इस तरह से बनाया गया कोई भी ViewModel ऑब्जेक्ट तब तक लाइव रहता है, जब तक संबंधित NavHost और उसके ViewModelStore को हटा दिया जाता है या नेविगेशन ग्राफ़, पिछली गतिविधियों से पॉप-अप हुआ हो.

नीचे दिए गए उदाहरण में, एक रेंज वाले ViewModel को वापस पाने का तरीका बताया गया है नेविगेशन ग्राफ़:

Kotlin

val viewModel: MyViewModel
        by navGraphViewModels(R.id.my_graph)

Java

NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.my_graph);
MyViewModel viewModel = new ViewModelProvider(backStackEntry).get(MyViewModel.class);

अगर नेविगेशन 2.2.0 या इससे पहले के वर्शन का इस्तेमाल किया जा रहा है, तो आपको खुद का नेविगेशन करना होगा इस्तेमाल करने के लिए फ़ैक्ट्री ViewModels के साथ सेव की गई स्थिति, जैसा कि नीचे दिए गए उदाहरण में दिखाया गया है:

Kotlin

val viewModel: MyViewModel by navGraphViewModels(R.id.my_graph) {
    SavedStateViewModelFactory(requireActivity().application, requireParentFragment())
}

Java

NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.my_graph);

ViewModelProvider viewModelProvider = new ViewModelProvider(
        backStackEntry.getViewModelStore(),
        new SavedStateViewModelFactory(
                requireActivity().getApplication(), requireParentFragment()));

MyViewModel myViewModel = provider.get(myViewModel.getClass());

ViewModel के बारे में ज़्यादा जानकारी के लिए, इसे देखें ViewModel की खास जानकारी.

इनफ़्लेटेड नेविगेशन ग्राफ़ में बदलाव करना

रनटाइम के दौरान, इनफ़्लेट किए गए नेविगेशन ग्राफ़ में डाइनैमिक तौर पर बदलाव किया जा सकता है.

उदाहरण के लिए, अगर आपके पास BottomNavigationView जो NavGraph से जुड़ा होता है, जो ऐप्लिकेशन शुरू होने पर, NavGraph चुने गए टैब को निर्देश देता है. हालांकि, आपको इस व्यवहार को ओवरराइड करने की ज़रूरत, जैसे कि जब कोई उपयोगकर्ता प्राथमिकता तय करती है ऐप्लिकेशन स्टार्टअप पर लोड होने के लिए पसंदीदा टैब. इसके अलावा, आपका ऐप्लिकेशन शायद उपयोगकर्ता के पिछले व्यवहार के आधार पर शुरुआती टैब में बदलाव करना ज़रूरी है. आप इन मामलों में मदद करने के लिए, NavGraph.

इस NavGraph को देखें:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/home">
    <fragment
        android:id="@+id/home"
        android:name="com.example.android.navigation.HomeFragment"
        android:label="fragment_home"
        tools:layout="@layout/fragment_home" />
    <fragment
        android:id="@+id/location"
        android:name="com.example.android.navigation.LocationFragment"
        android:label="fragment_location"
        tools:layout="@layout/fragment_location" />
    <fragment
        android:id="@+id/shop"
        android:name="com.example.android.navigation.ShopFragment"
        android:label="fragment_shop"
        tools:layout="@layout/fragment_shop" />
    <fragment
        android:id="@+id/settings"
        android:name="com.example.android.navigation.SettingsFragment"
        android:label="fragment_settings"
        tools:layout="@layout/fragment_settings" />
</navigation>

यह ग्राफ़ लोड होने पर, app:startDestination एट्रिब्यूट तय करता है कि HomeFragment दिखाना है. शुरुआती डेस्टिनेशन बदलने के लिए डाइनैमिक तौर पर, ये काम करें:

  1. सबसे पहले, NavGraph को मैन्युअल तरीके से बढ़ाएं.
  2. शुरुआती डेस्टिनेशन को बदलें.
  3. आखिर में, ग्राफ़ को NavController में मैन्युअल तरीके से अटैच करें.

Kotlin

val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment

val navController = navHostFragment.navController
val navGraph = navController.navInflater.inflate(R.navigation.bottom_nav_graph)
navGraph.startDestination = R.id.shop
navController.graph = navGraph
binding.bottomNavView.setupWithNavController(navController)

Java

NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager()
        .findFragmentById(R.id.nav_host_fragment);

NavController navController = navHostFragment.getNavController();
NavGraph navGraph = navController.getNavInflater().inflate(R.navigation.bottom_nav_graph);
navGraph.setStartDestination(R.id.shop);
navController.setGraph(navGraph);
NavigationUI.setupWithNavController(binding.bottomNavView, navController);

अब आपका ऐप्लिकेशन शुरू होने पर, HomeFragment के बजाय ShopFragment दिखेगा.

डीप लिंक का इस्तेमाल करते समय, NavController एक बैक स्टैक बनाता है डीप लिंक डेस्टिनेशन के लिए अपने-आप ट्रिगर हो जाएगा. अगर उपयोगकर्ता डीप लिंक पर जाता है और फिर पीछे की ओर जाता है. शुरुआत गंतव्य तक पहुंच सकता है या नहीं. पिछले उदाहरण में बताई गई तकनीक से यह पक्का होता है कि सही स्टार्ट डेस्टिनेशन को बनाए गए बैक स्टैक में जोड़ा गया है.

ध्यान दें कि इस तकनीक का इस्तेमाल करने पर, कन्वर्ज़न के अन्य पहलुओं को भी बदला जा सकता है NavGraph को ज़रूरत के मुताबिक. ग्राफ़ में सभी बदलाव किए जाने चाहिए setGraph() को कॉल करने से पहले, ताकि यह पक्का किया जा सके कि आपका स्ट्रक्चर सही है इसका इस्तेमाल डीप लिंक हैंडल करते समय, स्टेट को रीस्टोर करते समय, और शुरुआत में ले जाते समय किया जाता है डेस्टिनेशन (विज्ञापन के लिए सही दर्शक चुनना) की ज़रूरत नहीं है.