از Navigation 3 1.2.0، میتوانید
نتایج را از مقصدها بااستفاده از ResultEventBus
API برگردانید.
ResultEventBus دو مدل ارتباطی ارائه میدهد:
- نتایج رویدادمحور: برای رویدادهای گذرا و یکباره (مثل نمایش نوار اسنک تأیید یا راهاندازی اثر جانبی) بااستفاده از
ResultEffect. - نتایج مبتنی بر وضعیت: برای مشاهده آخرین نتیجه بهعنوان «نگارش»
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() } ) }
دریافت نتایج
مقصدها میتوانند نتایج را بااستفاده از جلوههای رویدادمحور یا مشاهدات حالتمحور مصرف کنند.
| API | رفتار | موارد استفاده توصیهشده |
|---|---|---|
ResultEffect |
در صف: همه نتایج منتشرشده برای کلید را بهترتیب پردازش میکند. | رویدادهای یکباره و عوارض جانبی (مثل نمایش نوار تنقلات یا بازارسال به ViewModel). |
conflateAsState |
ادغامشده: نتایج میانی را حذف میکند و فقط آخرین نتیجه را بهعنوان «نوشتن State» نگه میدارد. |
اصلاحکنندههای وضعیت میانای کاربر سبکوزن (مثل برچسبهای فیلتر فعال یا لغو انتخاب). |
مدیریت رویدادهای یکباره با ResultEffect
از ResultEffect هنگام مدیریت رویدادهای یکباره مثل
راهاندازی تجزیهوتحلیل، نمایش نوار اسنک، یا بازارسال نتیجه به
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بدنه اثر خود را برای هر نتیجهای که برای آن کلید ارسال شده است دریافت و اجرا میکند و همه انتشارها را به ترتیبی که ارسال شدهاند پردازش میکند. - گیرنده از ترکیب خارج میشود: وقتی مقصد گیرنده از پشته برگشت برداشته میشود،
ResultEffectاز ترکیب خارج میشود و دیگر به نتایج گوش نمیدهد.
مشاهده جدیدترین نتایج بهعنوان ایالت با conflateAsState
وقتی فقط به آخرین مقدار نتیجه برای اصلاح مستقیم یا فیلتر کردن وضعیت واسط کاربر محلی نیاز دارید و میخواهید هر زمان که نتیجه بهروز شد، Compose بهطور خودکار دوباره ترکیب کند، conflateAsState را در ResultEventBus فراخوانی کنید.
میتوانید نتایج مرتبط با یک کلید نتیجه صریح را مشاهده کنید:
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 ResultEventBus خود را بهصورت داخلی بااستفاده از rememberResultEventBus ایجاد و بهخاطر میسپارد.
وقتی نیاز دارید: میتوانید 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>()) پاک کنید. برای جزئیات مربوط به مطابقت کلید،
به کلیدهای نتیجه مراجعه کنید.
دستور پخت
برای دیدن نمونههای کامل کد اجرایی که استراتژیهای مختلف انتقال نتیجه را نشان میدهد، دستورالعملهای زیر را ببینید: