封裝導覽程式碼

使用 Kotlin DSL 建構圖表時,保留目的地並 維護單一檔案中的導覽事件並不容易。這是 特別是當您有多項各自獨立的功能時

擷取目的地

請將目的地移至「NavGraphBuilder擴充功能 函式。這些 Pod 必須居住在定義路徑的路徑附近 顯示在畫面上以下列應用程式層級程式碼為例 用於建立顯示聯絡人清單的目的地:

// 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 擴充功能函式構成無狀態的橋樑 畫面層級可組合函式和 Navigation 專屬的邏輯。這個圖層可以 也會定義狀態來源和處理事件的方式

範例

下列程式碼片段介紹的是顯示聯絡人的新目的地 詳細資料,並更新現有聯絡人清單目的地,以公開 導航活動,即可顯示聯絡人的詳細資料。

以下為可以設定專屬模組的一組常見畫面,例如 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 可組合函式此外,現在 含有提供畫面 UI 狀態的 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。在此情況下,請不要從 就能直接從 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 確保螢幕和路線類型不公開