NavController — Jetpack Compose'da özü, yöntemleri ve navigasyon yönetimi

Yazar: IT Sectr Yayınlanma: 2026-06-29 Okuma süresi: 7 dk

NavController, Navigation Compose kitaplığının Android uygulamalarında navigasyon yığınını ve back stack durumunu yöneten merkezi bileşenidir. NavController aracılığıyla ekranlar arası geçişler, önceki sayfalara dönüş ve rotalar arasında veri aktarımı gerçekleştirilir. Android Developers (2025)'e göre, NavController birden fazla ekrana sahip her Compose uygulamasının zorunlu bir öğesidir. Denetleyici rememberNavController() ile oluşturulur, NavHost'a iletilir ve kompozisyonun herhangi bir noktasından navigate() çağırmak için kullanılabilir. Yerleşik SavedStateHandle desteği, yeniden yapılandırma sırasında ViewModel durumunu otomatik olarak kaydeder.

Önemli Noktalar

  • NavController — Compose'un merkezi navigasyon denetleyicisi, back stack ve ekranlar arası geçişleri yönetir
  • navigate() — yığın yönetimi için NavOptions desteğiyle bir rotaya gitmenin ana yöntemi
  • popBackStack() — belirtilen bir rotaya kadar isteğe bağlı temizlikle önceki ekrana dönüş
  • SavedStateHandle — navigasyon sırasında ekran durumunu korumak için ViewModel ile entegrasyon
  • currentBackStackEntryAsState() — UI senkronizasyonu için mevcut rotanın gözlemlenmesi

Jetpack Compose'da NavController Nedir?

NavController, Navigation Compose kitaplığından Compose uygulamaları için navigasyon denetleyicisini uygulayan bir sınıftır. NavController, NavBackStackEntry yığınını yönetir; her giriş rota, argümanlar ve ekran durumunu içerir. Denetleyici temel navigasyon işlemlerini destekler: geçiş, dönüş, değiştirme ve temizlik.

Navigasyonun FragmentManager veya Intent ile yapıldığı View sisteminin aksine, NavController yalnızca Compose bağlamında çalışır. Back stack, Fragment yığını yerine NavDestination grafiği olarak depolanır. Bu, Fragment oluşturma ve yok etme yükünü ortadan kaldırır ve testi basitleştirir — NavController, TestNavHostController aracılığıyla mock'lanabilir.

NavController, NavHost ile yakından ilişkilidir — grafikten mevcut ekranı oluşturan bir kapsayıcı. NavHost olmadan, NavController composable işlevleri görüntüleyemez ancak yığını yönetme yeteneğini korur. Tipik bir mimaride, NavController Activity veya ana composable düzeyinde oluşturulur ve parametreler aracılığıyla kompozisyon ağacında aşağı iletilir.

Google'a göre, NavController birkaç büyük sürümden geçti. Sürüm 2.8.0 Type-Safe Navigation'ı ekledi, sürüm 2.9.0 predictive back gesture (Android 14+) desteğini ekledi. Denetleyici, Material3 Scaffold ve BottomNavigation ile uyumludur. Çok modüllü projeler için NavController, DI (Hilt/Koin) veya yapıcı parametreleri aracılığıyla iletilir.

NavController, composable işlevi rememberNavController() aracılığıyla oluşturulur. İşlev, mevcut composable'ın yaşam döngüsüne bağlı bir NavHostController (NavController'ın bir alt sınıfı) örneği döndürür. Kompozisyondan çıkıldığında, denetleyici temizlenir. Yeniden yapılandırma sırasında denetleyiciyi korumak için rememberSaveable veya ViewModel kullanın.

kotlin
@Composable
fun MyApp() {
    val navController = rememberNavController()
    NavHost(
        navController = navController,
        startDestination = "main"
    ) {
        composable("main") { MainScreen(navController) }
        composable("details") { DetailsScreen(navController) }
    }
}

NavController yapılandırması şunları içerir: NavHostController (ana), TestNavHostController (test) ve ScopedNavController (iç içe grafikler için alt). BottomNavigation için NavController tüm uygulama için tek olmalıdır — her sekmede yeni bir denetleyici oluşturmak yığın kaybına yol açar. Denetleyiciyi iç içe ekranlara iletmek için okunabilirliği korumak adına CompositionLocalProvider yerine bir işlev parametresi kullanın.

Navigasyon testi için compose-test-rule ile TestNavHostController kullanın. Denetleyici, başlangıç rotasını ayarlamaya ve navigate()'in beklenen geçişi tetiklediğini doğrulamaya olanak tanır. NavController'ı test etmek için emülatör gerekmez — Compose Test Semantics eşleştiricileriyle çalışır.

navigate(route: String) yöntemi, NavController'daki birincil navigasyon mekanizmasıdır. Bir rota dizesi, isteğe bağlı NavOptions ve Navigator.Extras kabul eder. NavOptions, geçiş davranışını kontrol eder: launchSingleTop (yığında rotayı çoğaltma), popUpTo (bir rotaya kadar yığını temizleme), restoreState (önceki durumu geri yükleme).

NavOptions, oluşturucu sözdizimiyle (NavOptionsBuilder) ayarlanır. Ana parametreler: popUpTo (rota + inclusive/saveState), launchSingleTop (Boolean, true — çoğaltma oluşturma), restoreState (dönüşte durumu geri yükleme). popUpTo olmadan, her navigate() yığına bir giriş ekler, bu da back stack birikmesine ve Back düğmesinin yanlış davranmasına yol açar.

kotlin
navController.navigate("profile/42") {
    popUpTo("main") { saveState = true }
    launchSingleTop = true
    restoreState = true
}

Navigator.Extras, rotanın parçası olmayan ek verileri (animasyon için paylaşılan öğeler, Intent bayrakları, Pac-Man paketi) iletmeye olanak tanır. Extras nadiren kullanılır — esas olarak Accompanist Animation veya özel Navigator ile entegrasyon için. Çoğu senaryo için bir rota dizesi ve NavOptions yeterlidir.

popBackStack: Dönüş ve Yığın Temizliği Yönetimi

popBackStack(), önceki ekrana dönme yöntemidir. Argümansız, yığının en üstündeki girişi kaldırır ve başarılı olursa true döndürür. Yığın boşsa, yöntem false döndürür ve Activity kapanır (super.onBackPressed()'e benzer).

Aşırı yüklenmiş sürüm popBackStack(route: String, inclusive: Boolean), belirtilen rotaya kadar tüm girişleri kaldırır. inclusive = true ise, belirtilen rotanın kendisi de kaldırılır. Yöntem Boolean döndürür — girişler bulunup kaldırıldıysa true. inclusive sürümü, yetkilendirme veya sipariş tamamlamadan sonra “kök ekrana çıkış” senaryoları için kullanışlıdır.

YöntemAçıklamaÖrnek
popBackStack()Bir ekran geri dönnavController.popBackStack()
popBackStack(route, false)route'a kadar temizle (route kalır)popBackStack(“home”, false)
popBackStack(route, true)route dahil temizlepopBackStack(“home”, true)
navigate(route) { popUpTo(route) { inclusive = true } }Tam temizlikle gezinnavigate(“login”) { popUpTo(0) { inclusive = true } }

Sistem Geri düğmesini (donanım geri düğmesi) işlemek için Compose'dan BackHandler kullanın. BackHandler, enabled ve onBack (basıldığında çağrılan geri çağrı) kabul eder. Android 14+ için, NavController sürüm 2.9.0'dan itibaren entegre edilen PredictiveBackGesture kullanılır. Predictive back, dönüş önizleme animasyonu ekler.

SavedStateHandle: Ekran Durumunu Koruma

SavedStateHandle, navigasyon ve yeniden yapılandırma sırasında ViewModel durumunu korumak için bir mekanizmadır. NavController, her NavBackStackEntry için otomatik olarak SavedStateHandle sağlar. SavedStateHandle aracılığıyla ViewModel ekran durumunu depolar ve dönüşte geri yükler (restoreState = true).

Navigation Compose'da SavedStateHandle, ViewModel ile birlikte kullanılır: ViewModel, backStackEntry'den iletilen SavedStateHandle aracılığıyla başlatılır. Başka bir ekrana gidip dönüldüğünde (restoreState ile), ViewModel yeniden oluşturulmak yerine kaydedilen durumu alır. Bu, veri girişi, filtreler veya kaydırma içeren ekranlar için kritiktir.

kotlin
class ProfileViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {
    val userId: String = savedStateHandle.get<String>("userId") ?: ""
    var searchQuery by savedStateHandle.getStateFlow("search", "")
        .collectAsState()
}

SavedStateHandle, ilkel türleri, String, Bundle ve Parcelable'ı destekler. Karmaşık nesneler için yalnızca kimlikleri kaydedin ve tam verileri depodan yükleyin. SavedStateHandle sınırı yaklaşık 1 MB'dır, aşılması TransactionTooLargeException'a neden olur. Büyük hacimler için handle'da kaydetmek yerine Room veya DataStore kullanın.

Önemli: SavedStateHandle yalnızca NavOptions'da restoreState = true kullanıldığında durumu korur. restoreState belirtilmezse, dönüşte ViewModel varsayılan değerlerle yeniden oluşturulur. restoreState ile BottomNavigation geçişi için NavController her sekmenin durumunu korur ve yeniden seçimde geri yükler.

currentBackStackEntryAsState ile Mevcut Rotayı Gözlemleme

currentBackStackEntryAsState(), State<NavBackStackEntry?> döndüren ve mevcut rota her değiştiğinde güncellenen bir işlevdir. Bu, navigasyonla UI senkronizasyonunun birincil mekanizmasıdır: BottomNavigation aktif öğeyi vurgular, Toolbar başlığı günceller, Drawer geçişte kapanır.

İşlev, snapshotFlow ve collectAsState aracılığıyla çalışır: back stack değiştiğinde Compose, abone olunan öğeleri yeniden oluşturur. Önemli: currentBackStackEntryAsState() yalnızca geçiş animasyonu tamamlandıktan sonra güncellenir. Anlık güncellemeler için, navigate() ile eşzamanlı olarak değişen ancak durumu desteklemeyen currentDestination'ı kullanın.

kotlin
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route

Text(
    text = when (currentRoute) {
        "home" -> "Home"
        "profile" -> "Profile"
        else -> ""
    }
)

Mevcut rotanın argümanlarına erişmek için navBackStackEntry?.arguments kullanın. Bu, BottomNavigation'da kullanışlıdır: selectedItem, currentRoute'a göre hesaplanır. Navigasyon hata ayıklaması için her geçişi günlüğe kaydeden NavController.addOnDestinationChangedListener() kullanın. Üretimde, çok sayıda composable içinde aboneliklerden kaçının — ViewModel'de tek bir kaynak oluşturun ve State'i UI'a iletin.

Sıkça Sorulan Sorular

Bir Activity'de birden fazla NavController oluşturulabilir mi?

Teknik olarak evet, ancak önerilmez. Tek bir NavController tutarlı back stack sağlar ve hata ayıklamayı basitleştirir. Birden fazla denetleyici yalnızca ayrı navigasyona sahip iç içe grafikler için haklıdır (örneğin, kendi yığınına sahip modal bottom sheet).

ViewModel aracılığıyla NavController nasıl iletilir?

NavController'ı ViewModel'e yapıcı veya DI aracılığıyla iletin. Ancak, NavController'ın kendisi yerine yalnızca geri çağrı işlevlerini (onNavigate, onBack) iletmek daha iyidir — bu testi basitleştirir. Olaylar için ViewModel'de Channel<NavEvent> kullanın ve UI'da toplayın.

Eşzamansız bir işlemden sonra navigate neden çalışmaz?

Sorun yaşam döngüsündedir: NavController henüz başlatılmamışsa (NavHost oluşturulmamışsa), navigate() yoksayılır. Veri yüklemesinden sonra navigasyonu çağırmak için rastgele yaşam döngüsüne sahip bir coroutine içinde değil, LaunchedEffect kullanın.

Tüm back stack nasıl temizlenir ve yeni bir ekrana gidilir?

navController.navigate(“hedef”) { popUpTo(0) { inclusive = true } } çağırın. popUpTo(0) parametresi yığını tamamen temizler, inclusive = true başlangıç girişini de kaldırır. launchSingleTop = true bayrağı yinelenen rotaları önler.

NavHostController ve NavController arasındaki fark nedir?

NavHostController, NavHost için ek yöntemlere (örneğin, setOnBackStackChangedListener) sahip NavController'ın bir alt sınıfıdır. NavController, programatik yığın yönetimi için NavHost dışında kullanılabilen temel sınıftır. Çoğu durumda NavHostController kullanılır.

Özet

  • NavController — Navigation Compose'un merkezi bileşeni, rota yığınını ve ekranlar arası geçişleri yönetir
  • navigate(), NavOptions aracılığıyla popUpTo, launchSingleTop ve restoreState ayarlarıyla geçişler gerçekleştirir
  • popBackStack() dönüşü yönetir: tek adım veya inclusive ile belirtilen rotaya kadar toplu temizlik
  • SavedStateHandle, navigasyon sırasında otomatik ekran durumu koruması için ViewModel ile entegre olur
  • currentBackStackEntryAsState(), UI senkronizasyonu için mevcut rotanın reaktif gözlemini sağlar
  • BackHandler sistem Geri düğmesini işler, PredictiveBackGesture NavController 2.9.0'dan itibaren desteklenir
  • Test için compose-test-rule ve Semantics eşleştiricileriyle TestNavHostController kullanın

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun