Đóng gói mã điều hướng của bạn

Khi sử dụng Kotlin DSL để tạo biểu đồ, hãy giữ lại các đích đến và sự kiện điều hướng trong một tệp có thể khó duy trì. Đây là đặc biệt đúng nếu bạn có nhiều tính năng độc lập.

Trích xuất đích đến

Bạn nên di chuyển các đích đến vào tiện ích NavGraphBuilder . Các dịch vụ này phải nằm gần các tuyến đường xác định chúng và mà chúng hiển thị. Ví dụ: hãy xem xét mã cấp ứng dụng sau đây để tạo một đích đến cho thấy danh sách người liên hệ:

// MyApp.kt

@Serializable
object Contacts

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

Bạn nên di chuyển mã điều hướng cụ thể vào một tệp riêng:

// ContactsNavigation.kt

@Serializable
object Contacts

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

// MyApp.kt

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

Các tuyến và định nghĩa đích đến hiện đã tách biệt với ứng dụng chính và bạn có thể tự cập nhật chúng. Ứng dụng chính chỉ phụ thuộc vào một hàm mở rộng. Trong trường hợp này, NavGraphBuilder.contactsDestination().

Hàm mở rộng NavGraphBuilder tạo thành cầu nối giữa một hàm không có trạng thái hàm có khả năng kết hợp cấp màn hình và logic Điều hướng dành riêng. Lớp này có thể bạn cũng cần xác định nguồn gốc của trạng thái và cách bạn xử lý các sự kiện.

Ví dụ

Đoạn mã sau đây giới thiệu một đích đến mới để hiển thị chi tiết và cập nhật đích đến của danh sách liên hệ hiện có để hiển thị sự kiện điều hướng để hiển thị thông tin chi tiết về người liên hệ đó.

Dưới đây là một nhóm màn hình điển hình có thể internal đối với mô-đun của riêng chúng, vì vậy mà các mô-đun khác không thể truy cập vào:

// 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) { ... }

Tạo đích đến

Hàm tiện ích NavGraphBuilder sau đây tạo một đích đến cho thấy thành phần kết hợp ContactsScreen. Ngoài ra, bây giờ màn hình có ViewModel cung cấp trạng thái giao diện người dùng màn hình và xử lý logic nghiệp vụ liên quan đến màn hình.

Các sự kiện điều hướng, chẳng hạn như di chuyển đến đích đến thông tin liên hệ, được hiển thị với phương thức gọi thay vì được ViewModel xử lý.

// 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
    )
  }
}

Bạn có thể sử dụng cùng một phương pháp để tạo đích đến hiển thị ContactDetailsScreen. Trong trường hợp này, thay vì lấy trạng thái giao diện người dùng từ view model, bạn có thể lấy trực tiếp từ NavBackStackEntry.

// ContactsNavigation.kt

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

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

Đóng gói sự kiện điều hướng

Tương tự như cách đóng gói đích đến, bạn có thể đóng gói các sự kiện điều hướng để tránh hiển thị loại tuyến đường một cách không cần thiết. Thực hiện việc này bằng cách tạo các hàm mở rộng trên NavController.

// ContactsNavigation.kt

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

Kết hợp

Mã điều hướng để hiển thị danh bạ hiện đã được tách biệt rõ ràng khỏi biểu đồ điều hướng của ứng dụng. Ứng dụng cần:

  • Gọi các hàm mở rộng NavGraphBuilder để tạo đích đến
  • Kết nối các đích đến đó bằng cách gọi hàm mở rộng NavController cho sự kiện điều hướng
// MyApp.kt

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

Tóm tắt

  • Đóng gói mã điều hướng của bạn cho một nhóm màn hình liên quan bằng cách đặt mã đó trong một tệp riêng biệt
  • Hiển thị đích đến bằng cách tạo các hàm mở rộng trên NavGraphBuilder
  • Hiển thị các sự kiện điều hướng bằng cách tạo hàm tiện ích trên NavController
  • Sử dụng internal để bảo mật màn hình và loại tuyến