پیمایش نحوه حرکت کاربران در برنامه شما را توصیف میکند. کاربران با عناصر میانای کاربر تعامل برقرار میکنند، معمولاً با تکضرب زدن یا کلیک کردن روی آنها، و برنامه با نمایش محتوای جدید پاسخ میدهد. اگر کاربر بخواهد به محتوای قبلی برگردد، از اشاره برگشت استفاده میکند یا روی دکمه برگشت تکضرب میزند.
مدلسازی وضعیت پیمایش
یک روش مناسب برای مدلسازی این رفتار، استفاده از پشته محتوا است. وقتی کاربر به محتوای جدید جلو میرود، این محتوا به بالای پشته اضافه میشود. وقتی کاربر از آن محتوا برمیگردد، آن محتوا از پشته خارج میشود و محتوای قبلی نمایش داده میشود. در اصطلاحات پیمایش، معمولاً به این پشته پشته قبلیها میگویند زیرا نشاندهنده محتوایی است که کاربر میتواند به آن برگردد.
ایجاد پشته قبلیها
در Navigation 3، پشته قبلیها درواقع حاوی محتوا نیست. درعوض، حاوی ارجاعاتی به محتوا است که بهعنوان کلید شناخته میشوند. کلیدها میتوانند از هر نوعی باشند اما معمولاً کلاسهای داده ساده و قابلسریالسازی هستند. استفاده از مرجع بهجای محتوا مزایای زیر را دارد:
- پیمایش با فشار دادن کلیدها روی پشته قبلیها ساده است.
- تا زمانی که کلیدها قابلسریالسازی باشند، پشته قبلیها را میتوان در فضای ذخیرهسازی پایدار ذخیره کرد تا بتواند دربرابر تغییرات پیکربندی و مرگ پردازش دوام بیاورد. این موضوع مهم است زیرا کاربران انتظار دارند وقتی از برنامهتان خارج میشوند و بعداً به آن برمیگردند، از همان جایی که برنامه را ترک کردهاند ادامه دهند و همان محتوا نمایش داده شود. برای اطلاعات بیشتر، ذخیره کردن پشته قبلیها را ببینید.
مفهوم کلیدی در Navigation 3 API این است که شما مالک پشته قبلیها هستید. کتابخانه:
- انتظار دارد که پشته قبلیها شما یک
List<T>با پشتیبانی حالت عکس آنی باشد، که در آنTنوعkeysپشته قبلیها شما است. میتوانید ازAnyاستفاده کنید یا کلیدهای خودتان را که نوع قویتری دارند ارائه دهید. وقتی اصطلاحات «push» یا «pop» را میبینید، پیادهسازی اساسی این است که موارد را از انتهای فهرست اضافه یا حذف کنید. - پشته قبلیها را مشاهده میکند و وضعیت آن را بااستفاده از
NavDisplayدر واسط کاربر منعکس میکند.
مثال زیر نشان میدهد که چگونه کلیدها و پشته قبلیها را ایجاد کنید و پشته قبلیها را در پاسخ به رویدادهای پیمایش کاربر اصلاح کنید:
// Define keys that will identify content data object ProductList data class ProductDetail(val id: String) @Composable fun MyApp() { // Create a back stack, specifying the key the app should start with val backStack = remember { mutableStateListOf<Any>(ProductList) } // Supply your back stack to a NavDisplay so it can reflect changes in the UI // ...more on this below... // Push a key onto the back stack (navigate forward), the navigation library will reflect the change in state backStack.add(ProductDetail(id = "ABC")) // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state backStack.removeLastOrNull() }
تبدیل کلیدها به محتوا
محتوا در Navigation 3 بااستفاده از NavEntry مدلسازی میشود که کلاسی حاوی تابع ترکیبپذیر است. این پشته نشاندهنده مقصد است - یک بخش
محتوا که کاربر میتواند به آن پیمایش کند و از آن برگردد.
NavEntry همچنین میتواند حاوی فراداده (اطلاعاتی درباره محتوا) باشد. این فراداده میتواند توسط اشیای نگهدارنده، مانند NavDisplay، خوانده شود تا به آنها کمک کند تصمیم بگیرند چگونه محتوای NavEntry را نمایش دهند. برای مثال، میتوان از فراداده برای لغو پویانماییهای پیشفرض برای NavEntry خاصی استفاده کرد. NavEntry
metadata نقشهای از کلیدهای String به مقادیر Any است که ذخیرهسازی دادههای همهکاره را فراهم میکند.
برای تبدیل key به NavEntry، یک «ارائهدهنده ورودی» ایجاد کنید. این یک
تابع است که key را میپذیرد و NavEntry را برای آن key برمیگرداند. معمولاً هنگام ایجاد NavDisplay بهعنوان پارامتر لامبدا تعریف میشود.
دو روش برای ایجاد «ارائهدهنده ورودی» وجود دارد: یا با ایجاد مستقیم تابع لامبدا، یا بااستفاده از DSL entryProvider.
ایجاد مستقیم تابع «ارائهدهنده ورودی»
معمولاً تابع «ارائهدهنده ورودی» را بااستفاده از عبارت when ایجاد میکنید، با
یک شاخه برای هرکدام از کلیدهایتان.
entryProvider = { key -> when (key) { is ProductList -> NavEntry(key) { Text("Product List") } is ProductDetail -> NavEntry( key, metadata = mapOf("extraDataKey" to "extraDataValue") ) { Text("Product ${key.id} ") } else -> { NavEntry(Unit) { Text(text = "Invalid Key: $it") } } } }
استفاده از DSL entryProvider
entryProvider DSL میتواند تابع لامبدا را با اجتناب از نیاز به آزمایش دربرابر هریک از انواع کلیدهای شما ساده کند و برای هرکدام یک NavEntry بسازد.
برای این کار، از تابع سازنده entryProvider استفاده کنید. همچنین شامل رفتار بازگشتی پیشفرض (نمایش خطا) درصورت پیدا نشدن کلید است.
entryProvider = entryProvider { entry<ProductList> { Text("Product List") } entry<ProductDetail>( metadata = mapOf("extraDataKey" to "extraDataValue") ) { key -> Text("Product ${key.id} ") } }
به موارد زیر در تکهکد توجه کنید:
entryبرای تعریفNavEntryبا نوع دادهشده و محتوای ترکیبپذیر استفاده میشودentryپارامترmetadataرا برای تنظیمNavEntry.metadataمیپذیرد
نمایش پشته قبلیها
پشته قبلیها نشاندهنده وضعیت پیمایش برنامه شما است. هرگاه پشته قبلیها تغییر میکند، واسط کاربر برنامه باید وضعیت جدید پشته قبلیها را منعکس کند. در Navigation 3، یک
NavDisplay پشته قبلیها را مشاهده میکند و واسط کاربر را براساس آن بهروز میکند. آن را با پارامترهای زیر بسازید:
- پشته قبلیها - این باید از نوع
SnapshotStateList<T>باشد، که در آنTنوع کلیدهای پشته قبلیها است. این یکListقابلمشاهده است تا هنگام تغییر، بازترکیبNavDisplayرا راهاندازی کند. - یک
entryProviderبرای تبدیل کلیدها در پشته قبلیها به اشیاءNavEntry. - درصورت تمایل، یک لامبدا به پارامتر
onBackارائه دهید. این زمانی فراخوانی میشود که کاربر رویداد برگشت را راهاندازی کند.
مثال زیر نحوه ایجاد NavDisplay را نشان میدهد.
data object Home data class Product(val id: String) @Composable fun NavExample() { val backStack = remember { mutableStateListOf<Any>(Home) } NavDisplay( backStack = backStack, onBack = { backStack.removeLastOrNull() }, entryProvider = { key -> when (key) { is Home -> NavEntry(key) { ContentGreen("Welcome to Nav3") { Button(onClick = { backStack.add(Product("123")) }) { Text("Click to navigate") } } } is Product -> NavEntry(key) { ContentBlue("Product ${key.id} ") } else -> NavEntry(Unit) { Text("Unknown route") } } } ) }
بهطور پیشفرض، NavDisplay بالاترین NavEntry را در پشته قبلیها در طرحبندی تکقاب نشان میدهد. ضبط زیر این برنامه را درحال اجرا نشان میدهد:
NavDisplay رفتار پیشفرض با دو
مقصد.چرخه حیات مقصد
NavDisplay از سفارشی LifecycleOwners برای محدود کردن وضعیت چرخه حیات
NavEntry براساس محدودیتهای سطح صحنه و محدودیتهای سطح
ورودی استفاده میکند.
برای اطلاعات بیشتر درباره چرخههای حیات در Compose، به چرخه حیات در Jetpack Compose مراجعه کنید.
محدودیتهای چرخه حیات در سطح صحنه
NavDisplay چرخه حیات Sceneهای فعال را مدیریت میکند. سقفهای سطح صحنه
بهصورت زیر تعیین میشود:
برای صحنههای غیرهمپوشان:
RESUMED: فقط زمانی مجاز است که انتقال صحنه انجام شده باشد و هیچ صحنه همپوشان فعالی روی آن نمایش داده نشود.STARTED: درطول انتقال صحنه، مثلاً هنگام پیمایش به جلو یا عقب، یا زمانی که با همپوشانی پوشانده شده است، بهSTARTEDمحدود میشود.
برای صحنههای همپوشان، مانند کادرهای گفتگو یا برگهای زیرین:
RESUMED: فقط برای بالاترین صحنه همپوشانی که درحالحاضر فعال است مجاز است.STARTED: برای هر صحنه رونهاد زیرین که با رونهاد جدیدتری پوشانده شده است، بهSTARTEDمحدود شده است.
وضعیت چرخه حیات سطح ورودی
کتابخانه حداکثر وضعیت چرخه حیات هر NavEntry را براساس حضور آن در پشته قبلیها مدیریت میکند:
RESUMED: اگر ورودی در پشته قبلیهای فعلی وجود داشته باشد، چرخه حیات آن میتواند تاRESUMEDبالا برود (مشروط به حد مجاز سطح صحنه).CREATED: اگر ورودی دیگر در پشته قبلیها نباشد، مثلاً وقتی که پاپ شده است اما همچنان درحال رندر شدن روی صفحه است درحالیکه پویانمایی خروج دارد، کتابخانه چرخه حیات آن را بهطور دقیق درCREATEDمحدود میکند. این محدودیت تضمین میکند که ورودیهای پسزمینه یا خروجی، اجرای کارهای فعال مانند جمعآوری جریانها یا راهاندازی کوروتینهای محدود به حالتهایRESUMEDیاSTARTEDرا درحین تکمیل انتقالهای خروجی خود متوقف کنند.
نحوه ترکیب شدن آنها
برای مثال، وضعیت چرخه حیات نهایی NavEntry بهصورت زیر حلوفصل میشود:
| سناریو | سقف سطح صحنه | سقف سطح ورودی | سقف مؤثر |
|---|---|---|---|
| ورودی فعال، صفحه ثابت (بدون انتقال یا همپوشانی) | RESUMED |
RESUMED |
RESUMED |
| ورودی فعال، درطول انتقال (پیمایش به یا از) | STARTED |
RESUMED |
STARTED |
| ورودی فعال، پوشاندهشده با همپوشانی (برای مثال، «کادر گفتگو» باز است) | STARTED |
RESUMED |
STARTED |
| ورودی پاپآپ، پویانمایی خروجی | STARTED یا RESUMED |
CREATED |
CREATED |
درحال سرهم کردن
نمودار زیر نحوه جریان دادهها بین اشیاء مختلف را در Navigation 3 نشان میدهد:
رویدادهای پیمایش تغییرات را آغاز میکنند. کلیدها در پاسخ به تعاملات کاربر به پشته قبلیها اضافه یا از آن برداشته میشوند.
تغییر در وضعیت پشته قبلیها باعث بازیابی محتوا میشود.
NavDisplay(یک composable که پشته قبلیها را ارائه میدهد) پشته قبلیها را مشاهده میکند. در پیکربندی پیشفرض، بالاترین ورودی پشته قبلیها را در چیدمان تکقاب نمایش میدهد. وقتی کلید بالایی در پشته قبلیها تغییر میکند،NavDisplayاز این کلید برای درخواست محتوای مربوطه از ارائهدهنده ورودی استفاده میکند.ارائهدهنده ورودی محتوا را تأمین میکند. ارائهدهنده ورودی تابعی است که کلید را به
NavEntryتبدیل میکند. پساز دریافت کلید ازNavDisplay، ارائهدهنده ورودیNavEntryمربوطه را ارائه میدهد که حاوی هم کلید و هم محتوا است.محتوا نمایش داده میشود.
NavDisplayNavEntryرا دریافت میکند و محتوا را نمایش میدهد.