Navigation 3 1.2.0 से, ResultEventBus एपीआई का इस्तेमाल करके, डेस्टिनेशन से नतीजे दिखाए जा सकते हैं.
ResultEventBus दो कम्यूनिकेशन मॉडल उपलब्ध कराता है:
- इवेंट पर आधारित नतीजे:
ResultEffectका इस्तेमाल करके, कुछ समय के लिए होने वाले इवेंट (जैसे, पुष्टि करने वाला स्नैकबार दिखाना या साइड इफ़ेक्ट ट्रिगर करना) के लिए. - स्टेट के आधार पर नतीजे: Compose
Stateके तौर पर सबसे नया नतीजा देखने के लिए,conflateAsStateका इस्तेमाल करें.
नतीजे के इवेंट बस को सेट अप करना
ResultEventBus को कंपोज़ किए जा सकने वाले डेस्टिनेशन के लिए उपलब्ध कराने के लिए, rememberResultEventBusNavEntryDecorator को NavDisplay को पास किए गए डेकोरेटर की सूची में जोड़ें. इससे हर डेस्टिनेशन के कॉन्टेंट को LocalResultEventBus
कंपोज़िशन लोकल के साथ दिखाया जाता है.
NavDisplay( /* ... */ entryDecorators = listOf( rememberSaveableStateHolderNavEntryDecorator(), rememberResultEventBusNavEntryDecorator() ) )
नतीजे की कुंजियां
ResultEventBus, हर नतीजे की पहचान करता है और उसे कुंजी का इस्तेमाल करके रूट करता है. भेजने वाले और पाने वाले, एक ही कुंजी का इस्तेमाल करके नतीजों का मिलान करते हैं.
नतीजे की कुंजियां दो तरीकों से तय की जा सकती हैं:
- एक्सप्लिसिट कुंजियां: एक्सप्लिसिट कुंजी (जैसे कि
resultKey = "pickup_address") तय की जा सकती है. सामान्य टाइप (जैसे किString,Booleanया प्रिमिटिव) दिखाने के लिए, एक्सप्लिसिट कुंजियों का इस्तेमाल करें. इसके अलावा, जब कई डेस्टिनेशन एक ही डेटा टाइप के अलग-अलग इंस्टेंस दिखाते हैं, तब भी एक्सप्लिसिट कुंजियों का इस्तेमाल करें. - टाइप से मिली कुंजियां: जब कोई कुंजी साफ़ तौर पर तय नहीं की जाती है, तो
ResultEventBus, नतीजे के टाइप केtoStringकेKClass(जैसे किContact::class.toString()) का इस्तेमाल करके अपने-आप एक कुंजी जनरेट करता है. अलग-अलग और डोमेन के हिसाब से डेटा टाइप के लिए, टाइप से मिली कुंजियों का इस्तेमाल करें.
किसी डेस्टिनेशन से नतीजे दिखाना
स्क्रीन कंपोज़ेबल को फिर से इस्तेमाल किया जा सकता है और उनकी जांच की जा सकती है. इसलिए, LocalResultEventBus को सीधे तौर पर अपनी स्क्रीन के यूज़र इंटरफ़ेस में ऐक्सेस न करें. इसके बजाय, अपनी स्क्रीन से कॉलबैक लैम्ब्डा दिखाएं. अपने entryProvider में, LocalResultEventBus.current का इस्तेमाल करके नतीजे भेजें और वापस जाएं.
नतीजे की कुंजी का इस्तेमाल करके नतीजे भेजे जा सकते हैं:
import androidx.compose.runtime.Composable import androidx.navigation3.runtime.result.LocalResultEventBus entry<AddressPickerRoute> { val resultBus = LocalResultEventBus.current AddressPickerScreen( onAddressSelected = { selectedAddress: Address -> resultBus.sendResult( resultKey = "pickup_address", result = selectedAddress ) navigator.goBack() } ) }
टाइप-डेराइव्ड कुंजी का इस्तेमाल करके भी नतीजे भेजे जा सकते हैं:
import androidx.compose.runtime.Composable import androidx.navigation3.runtime.result.LocalResultEventBus entry<ContactPickerRoute> { val resultBus = LocalResultEventBus.current ContactPickerScreen( onContactSelected = { selectedContact: Contact -> resultBus.sendResult(result = selectedContact) navigator.goBack() } ) }
नतीजे पाना
डेस्टिनेशन, इवेंट पर आधारित इफ़ेक्ट या स्टेट पर आधारित ऑब्ज़र्वेबल का इस्तेमाल करके नतीजे पा सकते हैं.
| एपीआई | व्यवहार | इस्तेमाल के सुझाए गए उदाहरण |
|---|---|---|
ResultEffect |
कतार में है: इस मोड में, किसी कुंजी के लिए मिले सभी नतीजों को क्रम से प्रोसेस किया जाता है. | एक बार होने वाले इवेंट और साइड इफ़ेक्ट (जैसे, स्नैकबार दिखाना या ViewModel पर फ़ॉरवर्ड करना). |
conflateAsState |
मिलाकर जवाब देना: इसमें बीच के नतीजे हटा दिए जाते हैं और सिर्फ़ सबसे नया नतीजा, कंपोज़ State के तौर पर दिखाया जाता है. |
लाइटवेट यूज़र इंटरफ़ेस (यूआई) की स्थिति में बदलाव करने वाले (जैसे कि चालू फ़िल्टर टैग या चुने गए आइटम को बदलने की सुविधा). |
ResultEffect की मदद से, एक बार होने वाले इवेंट मैनेज करना
ResultEffect का इस्तेमाल तब करें, जब आपको एक बार होने वाले इवेंट मैनेज करने हों. जैसे, Analytics को ट्रिगर करना, स्नैकबार दिखाना या ViewModel को नतीजे फ़ॉरवर्ड करना.
ResultEffect आने वाले नतीजों के लिए एक कतार बनाए रखता है. अगर किसी कुंजी के लिए एक से ज़्यादा नतीजे भेजे जाते हैं, तो ResultEffect हर नतीजे को उसी क्रम में प्रोसेस करता है जिस क्रम में उसे भेजा गया था. इसके अलावा, ResultEffect कोरूटीन स्कोप में चलता है. इससे आपको इफ़ेक्ट बॉडी में सीधे तौर पर सस्पेंड करने वाले फ़ंक्शन को कॉल करने की सुविधा मिलती है.
अश्लील कॉन्टेंट से जुड़ी नतीजे की कुंजी के नतीजे सुने जा सकते हैं:
import androidx.compose.runtime.Composable import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation3.runtime.result.ResultEffect @Composable fun RideSummaryScreen( onOpenAddressPicker: (key: String) -> Unit, viewModel: RideSummaryViewModel = viewModel() ) { ResultEffect<Address>(resultKey = "pickup_address") { address -> viewModel.onPickupAddressSelected(address) } ResultEffect<Address>(resultKey = "destination_address") { address -> viewModel.onDestinationAddressSelected(address) } RideSummaryContent( pickupAddress = viewModel.pickupAddress, destinationAddress = viewModel.destinationAddress, onPickPickup = { onOpenAddressPicker("pickup_address") }, onPickDestination = { onOpenAddressPicker("destination_address") } ) }
टाइप से मिली कुंजी का इस्तेमाल करके भी, नतीजे सुने जा सकते हैं:
import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation3.runtime.result.ResultEffect @Composable fun ComposeMessageScreen( onPickContact: () -> Unit, snackbarHostState: SnackbarHostState = remember { SnackbarHostState() }, viewModel: ComposeMessageViewModel = viewModel() ) { ResultEffect<Contact> { contact -> // Suspending calls are supported directly in the effect body snackbarHostState.showSnackbar("Selected ${contact.name}") viewModel.onRecipientSelected(contact) } ComposeMessageContent( recipient = viewModel.recipient, onPickContact = onPickContact ) }
एक डेस्टिनेशन से दूसरे डेस्टिनेशन पर नेविगेट करते समय, ResultEffect इन लाइफ़साइकल सीक्वेंस के ज़रिए काम करता है:
- सेंडर से नतीजे मिलते हैं: सेंडर डेस्टिनेशन,
resultBus.sendResult(resultKey = "pickup_address", address)का इस्तेमाल करके नतीजे भेजता है और पिछली गतिविधियों को पॉप करता है. - रिसीवर कंपोज़िशन में शामिल होता है: रिसीवर डेस्टिनेशन, ऐक्टिव स्क्रीन बन जाता है. साथ ही,
ResultEffectनतीजों को सुनने लगता है. - नतीजे पाने वाला, नतीजों को प्रोसेस करता है:
ResultEffectको उस कुंजी के लिए भेजे गए हर नतीजे के लिए, उसका इफ़ेक्ट बॉडी मिलता है और वह उसे लागू करता है. साथ ही, सभी उत्सर्जन को उसी क्रम में प्रोसेस करता है जिस क्रम में उन्हें भेजा गया था. - Receiver leaves composition: When the receiver destination is popped
from the back stack,
ResultEffectleaves composition and stops listening for results.
conflateAsState के साथ राज्य के हिसाब से चुनाव के नए नतीजे देखें
अगर आपको सिर्फ़ नतीजे की नई वैल्यू चाहिए, ताकि स्थानीय यूज़र इंटरफ़ेस (यूआई) की स्थिति में सीधे तौर पर बदलाव किया जा सके या उसे फ़िल्टर किया जा सके. साथ ही, आपको यह भी चाहिए कि नतीजा अपडेट होने पर, Compose अपने-आप फिर से कंपोज़ हो जाए, तो ResultEventBus पर conflateAsState को कॉल करें.
अश्लील कॉन्टेंट से जुड़ी नतीजे की कुंजी से जुड़े नतीजे देखे जा सकते हैं:
import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.graphics.Color import androidx.navigation3.runtime.result.LocalResultEventBus @Composable fun ThemePreviewScreen( onOpenColorPicker: (key: String) -> Unit ) { val resultBus = LocalResultEventBus.current val primaryColor by resultBus.conflateAsState<Color>( resultKey = "primary_color", defaultValue = MaterialTheme.colorScheme.primary ) val accentColor by resultBus.conflateAsState<Color>( resultKey = "accent_color", defaultValue = MaterialTheme.colorScheme.tertiary ) ThemePreviewContent( primaryColor = primaryColor, accentColor = accentColor, onPickPrimary = { onOpenColorPicker("primary_color") }, onPickAccent = { onOpenColorPicker("accent_color") } ) }
टाइप से मिली कुंजी का इस्तेमाल करके भी नतीजे देखे जा सकते हैं:
import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.navigation3.runtime.result.LocalResultEventBus @Composable fun FilterableProductListScreen( initialFilter: ProductFilter = ProductFilter.All, onOpenFilterPicker: () -> Unit ) { val resultBus = LocalResultEventBus.current // Observe latest filter result as Compose State, starting with initialFilter val activeFilter by resultBus.conflateAsState<ProductFilter>( defaultValue = initialFilter ) ProductListContent( activeFilter = activeFilter, onOpenFilterPicker = onOpenFilterPicker ) }
Hoist ResultEventBus
डिफ़ॉल्ट रूप से, rememberResultEventBusNavEntryDecorator rememberResultEventBus का इस्तेमाल करके, अंदरूनी तौर पर अपना ResultEventBus बनाता है और उसे सेव रखता है.
जब आपको ज़रूरत हो, तब ResultEventBus को साफ़ तौर पर बनाया और ऊपर किया जा सकता है:
ResultEventBusइंस्टेंस को सीधे तौर पर, कंपोज़ नहीं किए जा सकने वाले कॉम्पोनेंट या डिपेंडेंसी इंजेक्शन ग्राफ़ में पास करें.- डेस्टिनेशन के क्रम से बाहर, टॉप-लेवल के ऐप्लिकेशन के स्ट्रक्चर (जैसे कि ऐप्लिकेशन बार या नेविगेशन पैनल) से नतीजे भेजें या देखें.
ResultEventBus को ऊपर ले जाने के लिए, इसे rememberResultEventBus का इस्तेमाल करके बनाएं और इसे rememberResultEventBusNavEntryDecorator(resultEventBus) को पास करें:
import androidx.compose.runtime.Composable import androidx.navigation3.runtime.result.rememberResultEventBus import androidx.navigation3.runtime.result.rememberResultEventBusNavEntryDecorator import androidx.navigation3.ui.NavDisplay // Hoist the ResultEventBus at the top level val resultEventBus = rememberResultEventBus() // Pass the hoisted bus to the decorator val resultEventBusNavEntryDecorator = rememberResultEventBusNavEntryDecorator<NavKey>( resultEventBus = resultEventBus ) NavDisplay( /* ... */ entryDecorators = listOf( rememberSaveableStateHolderNavEntryDecorator(), resultEventBusNavEntryDecorator ) )
नतीजे मैनेज करना और हटाना
जब कोई डेस्टिनेशन, एक बार के नतीजे का इस्तेमाल कर लेता है, तो removeResult का इस्तेमाल करके, उसे इवेंट बस से हटा दें. इससे बस, डेस्टिनेशन के कंपोज़िशन में फिर से शामिल होने पर, नए ऑब्ज़र्वर को पिछले इवेंट फिर से डिलीवर नहीं करती:
import androidx.compose.runtime.Composable import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation3.runtime.result.LocalResultEventBus import androidx.navigation3.runtime.result.ResultEffect @Composable fun NotificationSettingsScreen( viewModel: NotificationViewModel = viewModel() ) { val resultBus = LocalResultEventBus.current ResultEffect<ConfirmationResult>(resultKey = "confirm_permission") { confirmation -> viewModel.onPermissionConfirmed(confirmation) // Clear the result after consumption to prevent re-delivery resultBus.removeResult(resultKey = "confirm_permission") } }
नतीजों को साफ़ तौर पर बताई गई कुंजी (resultBus.removeResult(resultKey)) या टाइप से मिली कुंजी (resultBus.removeResult<T>()) के हिसाब से हटाया जा सकता है. कुंजी मिलान के बारे में ज़्यादा जानने के लिए, नतीजे की कुंजियां देखें.
रेसिपी
नतीजे पास करने की अलग-अलग रणनीतियों को दिखाने वाले, चलाए जा सकने वाले कोड के उदाहरणों के लिए, यहां दी गई रेसिपी देखें:
- इवेंट के हिसाब से खोज नतीजों में दिखने वाली रेसिपी
- राज्य के हिसाब से नतीजे दिखाने वाली रेसिपी
- सीरियलाइज़ किए जा सकने वाले नतीजे की रेसिपी