ذخیره و مدیریت وضعیت ناوبری

بخش‌های زیر راهبردهای ذخیره کردن پشته قبلی‌ها و ذخیره کردن وضعیت مرتبط با ورودی‌های پشته قبلی‌ها را شرح می‌دهد.

ذخیره کردن پشته قبلی‌ها

اطمینان از اینکه وضعیت پیمایش برنامه شما در رویدادهای مختلف چرخه حیات، ازجمله تغییرات پیکربندی و مرگ پردازش، پایدار می‌ماند، برای تجربه کاربری خوب بسیار مهم است. در Navigation 3، پشته قبلی‌ها متعلق به شما است، بنابراین دستورالعمل‌های سخت‌گیرانه‌ای درباره نحوه ایجاد یا ذخیره آن وجود ندارد. بااین‌حال، Navigation 3 روشی راحت ارائه می‌دهد که پشته قبلی‌ها قابل‌ذخیره را دراختیارتان قرار می‌دهد: rememberNavBackStack.

استفاده از rememberNavBackStack

تابع ترکیب‌پذیر rememberNavBackStack برای ایجاد پشته قبلی‌ها طراحی شده است که در تغییرات پیکربندی و مرگ پردازش پایدار می‌ماند.

برای اینکه rememberNavBackStack به‌درستی کار کند، هر کلید در پشته قبلی‌ها باید از الزامات خاصی پیروی کند:

  • پیاده‌سازی میانای NavKey: هر کلید در پشته قبلی‌ها باید میانای NavKey را پیاده‌سازی کند. این به‌عنوان میانای نشانگر عمل می‌کند که به کتابخانه علامت می‌دهد که کلید می‌تواند ذخیره شود.
  • حاشیه نویسی @Serializable را داشته باشید: علاوه‌بر پیاده‌سازی NavKey، کلاس‌ها و اشیاء کلیدی شما باید با حاشیه نویسی @Serializable علامت‌گذاری شوند.

قطعه کد زیر پیاده‌سازی صحیح rememberNavBackStack را نشان می‌دهد:

@Serializable
data object Home : NavKey

@Composable
fun NavBackStack() {
    val backStack = rememberNavBackStack(Home)
}

به‌خاطر سپردن پشته قبلی‌ها با زیرنوع‌های NavKey

تابع ترکیب‌پذیر rememberNavBackStack یک NavBackStack<NavKey> برمی‌گرداند. اگر برنامه شما زیرنوع خودش را از NavKey تعریف می‌کند که همه کلیدهایش از آن به‌ارث می‌برند، می‌توانید آن تایپ را با پیاده‌سازی تابع remember سفارشی به‌صورت زیر حفظ کنید:

@Serializable
sealed interface MyAppNavKey : NavKey

@Serializable
data object ScreenA: MyAppNavKey

@Serializable
data class ScreenB(val id: String): MyAppNavKey

@Composable
fun rememberMyAppNavBackStack(vararg elements: MyAppNavKey): NavBackStack<MyAppNavKey> {
    return rememberSerializable(serializer = serializer()) {
        NavBackStack(*elements)
    }
}

@Composable
fun MyApp() {
    // defaultNavBackStack is NavBackStack<NavKey>
    val defaultNavBackStack = rememberNavBackStack(ScreenA)
    // myAppNavBackStack is NavBackStack<MyAppNavKey>
    val myAppNavBackStack = rememberMyAppNavBackStack(ScreenA)
}

برای مثال‌های بیشتر (ازجمله نحوه مدیریت چندریختی باز)، به NavBackStackSamples مراجعه کنید.

جایگزین: ذخیره در ViewModel

رویکرد دیگر برای مدیریت پشته قبلی‌ها ذخیره کردن آن در ViewModel است. برای پایداری درصورت مرگ پردازش هنگام استفاده از ViewModel یا هر فضای ذخیره‌سازی سفارشی دیگر، باید:

  • مطمئن شوید کلیدهایتان قابل‌سریال‌سازی باشند: درست مانند rememberNavBackStack، کلیدهای پیمایش شما باید قابل‌سریال‌سازی باشند.
  • مدیریت دستی سریال‌سازی و غیرسریال‌سازی: شما مسئول هستید که نمایش سریال‌سازی‌شده هر کلید را به‌صورت دستی در فضای ذخیره‌سازی پایدار (مثلاً SharedPreferences، پایگاه داده، یا فایل) ذخیره کنید و آن را از آنجا غیرسریال‌سازی کنید، زمانی که برنامه‌تان به پس‌زمینه می‌رود یا بازیابی می‌شود.

درحال محدود کردن ViewModel نمونه به NavEntry شیء

از ViewModels برای حفظ حالت مربوط به میانای کاربر در تغییرات پیکربندی، مانند چرخش صفحه‌نمایش، استفاده می‌شود. به‌طور پیش‌فرض، ViewModels به نزدیک‌ترین ViewModelStoreOwner محدود می‌شود که معمولاً Activity یا Fragment شما است.

بااین‌حال، ممکن است بخواهید به‌جای کل Activity، یک ViewModel را به یک NavEntry خاص (یعنی یک صفحه یا مقصد خاص) در پشته قبلی‌ها محدود کنید. این کار تضمین می‌کند که وضعیت ViewModel فقط زمانی حفظ می‌شود که NavEntry خاص بخشی از پشته قبلی‌ها باشد و وقتی NavEntry پاپ شود، پاک می‌شود.

کتابخانه برافزای androidx.lifecycle:lifecycle-viewmodel-navigation3 NavEntryDecorator را ارائه می‌دهد که این کار را تسهیل می‌کند. این دکوراتور یک ViewModelStoreOwner برای هر NavEntry ارائه می‌دهد. وقتی ViewModel را در محتوای NavEntry ایجاد می‌کنید (مثلاً بااستفاده از viewModel() در Compose)، به‌طور خودکار به کلید آن NavEntry خاص در پشته قبلی‌ها محدود می‌شود. این یعنی ViewModel وقتی ایجاد می‌شود که NavEntry به پشته قبلی‌ها اضافه شود، و وقتی برداشته شود پاک می‌شود.

برای استفاده از NavEntryDecorator برای محدود کردن ViewModel به NavEntry، این مراحل را دنبال کنید:

  1. وابستگی androidx.lifecycle:lifecycle-viewmodel-navigation3 را به فایل app/build.gradle.kts اضافه کنید.
  2. rememberSaveableStateHolderNavEntryDecorator() پیش‌فرض را هنگام ساختن NavDisplay به فهرست entryDecorators اضافه کنید.
  3. rememberViewModelStoreNavEntryDecorator() را به فهرست entryDecorators اضافه کن.

NavDisplay(
    entryDecorators = listOf(
        // Add the default decorators for managing scenes and saving state
        rememberSaveableStateHolderNavEntryDecorator(),
        // Then add the view model store decorator
        rememberViewModelStoreNavEntryDecorator()
    ),
    backStack = backStack,
    entryProvider = entryProvider { },
)