Navigation 3 1.2.0 সংস্করণ থেকে, আপনি ResultEventBus API ব্যবহার করে গন্তব্যস্থল থেকে ফলাফল ফেরত আনতে পারবেন।
ResultEventBus দুটি যোগাযোগ মডেল প্রদান করে:
- ইভেন্ট-ভিত্তিক ফলাফল :
ResultEffectব্যবহার করে ক্ষণস্থায়ী, এককালীন ইভেন্টের (যেমন একটি কনফার্মেশন স্নাকবার দেখানো বা কোনো সাইড ইফেক্ট ট্রিগার করা) জন্য। - স্টেট-ভিত্তিক ফলাফল :
conflateAsStateব্যবহার করে কম্পোজStateহিসেবে সর্বশেষ ফলাফল পর্যবেক্ষণ করার জন্য।
ফলাফল ইভেন্ট বাস সেট আপ করুন
আপনার কম্পোজেবল ডেস্টিনেশনগুলিতে ResultEventBus উপলব্ধ করতে, আপনার NavDisplay তে পাস করা ডেকোরেটরগুলির তালিকায় rememberResultEventBusNavEntryDecorator যোগ করুন। এটি প্রতিটি ডেস্টিনেশনের কন্টেন্টকে একটি LocalResultEventBus কম্পোজিশন লোকাল প্রদান করে।
NavDisplay( /* ... */ entryDecorators = listOf( rememberSaveableStateHolderNavEntryDecorator(), rememberResultEventBusNavEntryDecorator() ) )
ফলাফলের চাবিগুলি
ResultEventBus একটি কী ব্যবহার করে প্রতিটি ফলাফল শনাক্ত ও রাউট করে। প্রেরক এবং প্রাপক একই কী ব্যবহার করে ফলাফল মেলায়।
আপনি দুইভাবে ফলাফল কী নির্দিষ্ট করতে পারেন:
- সুস্পষ্ট কী : আপনি একটি সুস্পষ্ট কী নির্দিষ্ট করতে পারেন (যেমন
resultKey = "pickup_address")। সাধারণ টাইপ (যেমনString,Boolean, বা প্রিমিটিভ) রিটার্ন করার সময়, অথবা যখন একাধিক গন্তব্য একই ডেটা টাইপের ভিন্ন ভিন্ন ইনস্ট্যান্স রিটার্ন করে, তখন সুস্পষ্ট কী ব্যবহার করুন। - টাইপ-ডিরাইভড কী : যখন আপনি কোনো সুস্পষ্ট কী নির্দিষ্ট করেন না, তখন
ResultEventBusস্বয়ংক্রিয়ভাবে রেজাল্ট টাইপেরKClassএরtoStringরিপ্রেজেন্টেশন ব্যবহার করে একটি কী তৈরি করে (যেমনContact::class.toString())। স্বতন্ত্র, ডোমেইন-নির্দিষ্ট ডেটা টাইপের জন্য টাইপ-ডিরাইভড কী ব্যবহার করুন।
একটি গন্তব্য থেকে ফলাফল ফেরত দিন
স্ক্রিন কম্পোজেবলগুলোকে পুনঃব্যবহারযোগ্য ও পরীক্ষাযোগ্য রাখতে, আপনার স্ক্রিন UI-এর ভেতরে সরাসরি 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 হিসেবে শুধুমাত্র সর্বশেষ ফলাফলটি রাখে। | হালকা UI স্টেট মডিফায়ার (যেমন সক্রিয় ফিল্টার ট্যাগ বা সিলেকশন ওভাররাইড)। |
ResultEffect ব্যবহার করে এককালীন ইভেন্টগুলো পরিচালনা করুন
অ্যানালিটিক্স চালু করা, স্নাকবার প্রদর্শন করা, বা কোনো ফলাফল ViewModel এ ফরোয়ার্ড করার মতো এককালীন ইভেন্টগুলি পরিচালনা করার জন্য ResultEffect ব্যবহার করুন।
ResultEffect আগত ফলাফলের জন্য একটি কিউ (queue) রক্ষণাবেক্ষণ করে। যদি কোনো নির্দিষ্ট কী (key)-এর জন্য একাধিক ফলাফল পাঠানো হয়, তবে ResultEffect প্রতিটি ফলাফলকে পাঠানোর ক্রমানুসারে প্রসেস করে। এছাড়াও, ResultEffect একটি কো-রুটিন (coroutine) স্কোপে চলে, যা আপনাকে ইফেক্ট বডির ভেতরে সরাসরি সাসপেন্ডিং (suspending) ফাংশন কল করার সুযোগ দেয়।
আপনি একটি সুস্পষ্ট ফলাফল কী- এর সাথে সম্পর্কিত ফলাফল শুনতে পারেন:
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সেই কী-এর জন্য পাঠানো প্রতিটি ফলাফলের জন্য তার এফেক্ট বডি গ্রহণ ও কার্যকর করে এবং প্রেরণের ক্রমানুসারে সমস্ত এমিশন প্রক্রিয়াকরণ করে। - রিসিভার কম্পোজিশন ত্যাগ করে : যখন ব্যাক স্ট্যাক থেকে রিসিভার ডেস্টিনেশনটি পপ করা হয়, তখন
ResultEffectকম্পোজিশন ত্যাগ করে এবং ফলাফলের জন্য শোনা বন্ধ করে দেয়।
conflateAsState ব্যবহার করে সর্বশেষ ফলাফলকে স্টেট হিসেবে পর্যবেক্ষণ করুন।
যখন স্থানীয় UI স্টেট সরাসরি পরিবর্তন বা ফিল্টার করার জন্য আপনার শুধুমাত্র সর্বশেষ ফলাফলের মান প্রয়োজন এবং আপনি চান যে ফলাফল আপডেট হওয়ার সাথে সাথে 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 ) }
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>() ) ব্যবহার করে ফলাফল মুছে ফেলতে পারেন। কী মেলানোর বিষয়ে বিস্তারিত জানতে, ফলাফলের কী (Result keys ) দেখুন।
রেসিপি
বিভিন্ন ফলাফল-প্রদান কৌশল প্রদর্শনকারী সম্পূর্ণ কার্যকর কোড উদাহরণের জন্য, নিম্নলিখিত রেসিপিগুলো দেখুন: