Gezinme kodunuzu kapsülleyin

Grafiğinizi oluşturmak için Kotlin DSL'yi kullanırken, hedefleri ve gezinme etkinliklerini tek bir dosyada tutmak zor olabilir. Bu, özellikle birden fazla bağımsız özelliğiniz varsa geçerlidir.

Hedefleri çıkar

Hedeflerinizi NavGraphBuilder uzantı işlevlerine taşımanız gerekir. Kendilerini tanımlayan rotalara ve gösterdikleri ekranlara yakın bir yerde yaşamaları gerekir. Örneğin, kişiler listesini gösteren bir hedef oluşturan aşağıdaki uygulama düzeyinde kodu düşünün:

// MyApp.kt

@Serializable
object Contacts

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

Gezinmeye özel kodu ayrı bir dosyaya taşımanız gerekir:

// ContactsNavigation.kt

@Serializable
object Contacts

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

// MyApp.kt

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

Rotalar ve hedef tanımları artık ana uygulamadan ayrıdır ve bunları bağımsız olarak güncelleyebilirsiniz. Ana uygulama yalnızca tek bir uzantı işlevine bağımlıdır. Bu örnekte, bu NavGraphBuilder.contactsDestination() olur.

NavGraphBuilder uzantı işlevi, durum bilgisiz ekran düzeyinde composable işlev ile Gezinme'ye özgü mantık arasında köprü oluşturur. Bu katman, durumun nereden geldiğini ve etkinlikleri nasıl yöneteceğinizi de tanımlayabilir.

Örnek

Aşağıdaki snippet, bir kişinin ayrıntılarını görüntülemek için yeni bir hedef sunar ve kişinin ayrıntılarını görüntülemek için mevcut kişi listesi hedefini bir gezinme etkinliği gösterecek şekilde günceller.

Diğer modüllerin bunlara erişememesi için kendi modülüne internal olabilen tipik bir ekran kümesini burada görebilirsiniz:

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

Hedef oluşturma

Aşağıdaki NavGraphBuilder uzantı işlevi, ConversationScreen composable'ı gösteren bir hedef oluşturur. Ayrıca artık ekranı, ekran kullanıcı arayüzü durumunu sağlayan ve ekranla ilgili iş mantığını işleyen bir ViewModel ile bağlar.

Kişi ayrıntıları hedefine gitme gibi navigasyon etkinlikleri, ViewModel tarafından yönetilmek yerine arayana gösterilir.

// 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 öğesinin gösterildiği bir hedef oluşturmak için de aynı yaklaşımı kullanabilirsiniz. Bu durumda, kullanıcı arayüzü durumunu bir görünüm modelinden almak yerine, durumu doğrudan NavBackStackEntry üzerinden alabilirsiniz.

// ContactsNavigation.kt

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

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

Gezinme etkinliklerini kapsülle

Hedefleri kapsüllediğiniz gibi, rota türlerini gereksiz yere göstermekten kaçınmak için navigasyon etkinliklerini kapsülleyebilirsiniz. Bu işlemi, NavController üzerinde uzantı işlevleri oluşturarak yapabilirsiniz.

// ContactsNavigation.kt

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

Hepsini bir araya getirin

Kişileri görüntülemek için kullanılan gezinme kodu artık uygulamanın gezinme grafiğinden net bir şekilde ayrı tutulmuştur. Uygulama şunları yapmalıdır:

  • Hedef oluşturmak için NavGraphBuilder uzantısı işlevlerini çağırın
  • Rota izleme etkinlikleri için NavController uzantı işlevlerini çağırarak bu hedefleri bağlayın
// MyApp.kt

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

Özet

  • Gezinme kodunuzu ilgili ekran grupları için ayrı bir dosyaya yerleştirerek kapsülleyin.
  • NavGraphBuilder üzerinde uzantı işlevleri oluşturarak hedefleri gösterin
  • NavController üzerinde uzantı işlevleri oluşturarak gezinme etkinliklerini gösterin
  • Ekranları ve rota türlerini gizli tutmak için internal öğesini kullanın