کد ناوبری خود را کپسوله کنید

هنگامی که از Kotlin DSL برای ساخت نمودار خود استفاده می کنید، نگهداری مقصدها و رویدادهای ناوبری در یک فایل ممکن است دشوار باشد. این امر به ویژه در صورتی صادق است که چندین ویژگی مستقل داشته باشید.

استخراج مقاصد

شما باید مقصد خود را به توابع افزونه NavGraphBuilder منتقل کنید. آنها باید نزدیک به مسیرهایی که آنها را مشخص می کند و صفحه نمایش هایی که آنها نمایش می دهند زندگی کنند. به عنوان مثال، کد زیر را در سطح برنامه در نظر بگیرید که مقصدی را ایجاد می کند که لیستی از مخاطبین را نشان می دهد:

// MyApp.kt

@Serializable
object Contacts

@Composable
fun MyApp() {
  ...
  NavHost(navController, startDestination = Contacts) {
    composable<Contacts> { ContactsScreen( /* ... */ ) }
  }
}

شما باید کد ناوبری خاص را به یک فایل جداگانه منتقل کنید:

// ContactsNavigation.kt

@Serializable
object Contacts

fun NavGraphBuilder.contactsDestination() {
    composable<Contacts> { ContactsScreen( /* ... */ ) }
}

// MyApp.kt

@Composable
fun MyApp() {
  ...
  NavHost(navController, startDestination = Contacts) {
     contactsDestination()
  }
}

مسیرها و تعاریف مقصد اکنون جدا از برنامه اصلی هستند و می توانید آنها را به طور مستقل به روز کنید. برنامه اصلی تنها به یک تابع برنامه افزودنی وابسته است. در این مورد، NavGraphBuilder.contactsDestination() است.

تابع پسوند NavGraphBuilder پل بین یک تابع قابل ترکیب در سطح صفحه نمایش بدون حالت و منطق خاص ناوبری را تشکیل می دهد. این لایه همچنین می‌تواند مشخص کند که وضعیت از کجا می‌آید و چگونه رویدادها را مدیریت می‌کنید.

مثال

قطعه زیر یک مقصد جدید را برای نمایش جزئیات مخاطب معرفی می‌کند و مقصد فهرست مخاطبین موجود را به‌روزرسانی می‌کند تا یک رویداد ناوبری برای نمایش جزئیات مخاطب نمایش داده شود.

در اینجا مجموعه‌ای از صفحه‌نمایش‌ها وجود دارد که می‌توانند internal ماژول خودشان باشند، به طوری که ماژول‌های دیگر نتوانند به آنها دسترسی داشته باشند:

// ContactScreens.kt

// Displays a list of contacts
@Composable
internal fun ContactsScreen(
  uiState: ContactsUiState,
  onNavigateToContactDetails: (contactId: String) -> Unit
) { ... }

// Displays the details for an individual contact
@Composable
internal fun ContactDetailsScreen(contact: ContactDetails) { ... }

مقاصد ایجاد کنید

تابع پسوند NavGraphBuilder زیر مقصدی را ایجاد می کند که ContactsScreen قابل ترکیب را نشان می دهد. علاوه بر این، اکنون صفحه را با ViewModel متصل می کند که وضعیت رابط کاربری صفحه را ارائه می دهد و منطق تجاری مربوط به صفحه نمایش را مدیریت می کند.

رویدادهای ناوبری، مانند پیمایش به مقصد جزئیات تماس، به جای اینکه توسط ViewModel مدیریت شوند، در معرض تماس گیرنده قرار می گیرند.

// ContactsNavigation.kt

@Serializable
object Contacts

// Adds contacts destination to `this` NavGraphBuilder
fun NavGraphBuilder.contactsDestination(
  // Navigation events are exposed to the caller to be handled at a higher level
  onNavigateToContactDetails: (contactId: String) -> Unit
) {
  composable<Contacts> {
    // The ViewModel as a screen level state holder produces the screen
    // UI state and handles business logic for the ConversationScreen
    val viewModel: ContactsViewModel = hiltViewModel()
    val uiState = viewModel.uiState.collectAsStateWithLifecycle()
    ContactsScreen(
      uiState,
      onNavigateToContactDetails
    )
  }
}

می توانید از همین رویکرد برای ایجاد مقصدی استفاده کنید که ContactDetailsScreen نمایش دهد. در این حالت، به جای به دست آوردن حالت رابط کاربری از یک مدل view، می توانید آن را مستقیماً از NavBackStackEntry دریافت کنید.

// ContactsNavigation.kt

@Serializable
internal data class ContactDetails(val id: String)

fun NavGraphBuilder.contactDetailsScreen() {
  composable<ContactDetails> { navBackStackEntry ->
    ContactDetailsScreen(contact = navBackStackEntry.toRoute())
  }
}

رویدادهای ناوبری را کپسوله کنید

به همان روشی که مقصدها را کپسوله می‌کنید، می‌توانید رویدادهای ناوبری را برای جلوگیری از افشای غیرضروری انواع مسیرها کپسوله کنید. این کار را با ایجاد توابع افزونه در NavController انجام دهید.

// ContactsNavigation.kt

fun NavController.navigateToContactDetails(id: String) {
  navigate(route = ContactDetails(id = id))
}

آن را با هم بیاورید

کد پیمایش برای نمایش مخاطبین اکنون کاملاً از نمودار ناوبری برنامه جدا شده است. برنامه باید:

  • برای ایجاد مقصد، توابع افزونه NavGraphBuilder را فراخوانی کنید
  • آن مقاصد را با فراخوانی توابع برنامه افزودنی NavController برای رویدادهای ناوبری متصل کنید
// MyApp.kt

@Composable
fun MyApp() {
  ...
  NavHost(navController, startDestination = Contacts) {
     contactsDestination(onNavigateToContactDetails = { contactId ->
        navController.navigateToContactDetails(id = contactId)
     })
     contactDetailsDestination()
  }
}

به طور خلاصه

  • کد ناوبری خود را با قرار دادن آن در یک فایل جداگانه برای مجموعه ای از صفحه های مربوطه در محفظه قرار دهید
  • با ایجاد توابع افزونه در NavGraphBuilder ، مقاصد را در معرض دید قرار دهید
  • رویدادهای ناوبری را با ایجاد توابع افزونه در NavController نشان دهید
  • برای خصوصی نگه داشتن صفحه نمایش و انواع مسیرها از internal استفاده کنید