composable(): NavHost ve Jetpack Compose'da yönlendirme

Yazar: IT Sectr Yayınlanma: 2026-06-30 Okuma süresi: 9 dk

composable(), Navigation Compose kütüphanesinin bir fonksiyonu olup, NavHost'a bir ekran kaydeder ve URL rotasını Compose düzenine bağlar. Navigasyon belirli bir rotaya gittiğinde, Jetpack Compose ilgili composable fonksiyonunu çağırır ve onu geçerli ekran olarak görüntüler. FragmentManager veya Intent tabanlı navigasyonun aksine, composable() tek bir Activity düzeyinde çalışır ve tamamen Kotlin DSL aracılığıyla yönetilir. Android Developers (2025)'a göre, Jetpack Compose ile oluşturulmuş modern Android uygulamalarının %73'ünden fazlası ekran geçişlerini düzenlemek için Navigation Compose kullanır.

Önemli Noktalar

  • composable(), Navigation Compose kütüphanesinin NavHost'una ekran kaydeden bir fonksiyondur.
  • Rota — her ekran, ilk argüman olarak iletilen bir dize rotasıyla tanımlanır.
  • Parametreler — composable(), NavArgument aracılığıyla zorunlu ve isteğe bağlı argümanları destekler.
  • İç içe yerleştirme — ayrı rota grafiklerine sahip iç içe NavHost'lar aracılığıyla iç içe navigasyon desteklenir.
  • Performans — composable() geç başlatma kullanır: ekran yalnızca ilk navigasyonda oluşturulur.

NavHost'te composable() nedir

composable(), NavHost nesnesinin bir genişletme fonksiyonudur. Kotlin DSL, uygulamanın tüm ekranlarını bildirimsel olarak tanımlamak için NavHost bloğu içinde çağrılmasına izin verir. Her çağrı, navigasyon grafiğinde bir girdi oluşturarak bir dize rotasını composable fonksiyonuna bağlar. Bir kullanıcı belirli bir rotaya gittiğinde, NavHost önceki ekranı gizleyerek ilgili composable'ı geçerli ekran olarak görüntüler.

Navigation Compose kütüphanesi, Google tarafından 2021 yılında Jetpack Compose için Fragment tabanlı navigasyona alternatif olarak tanıtıldı. Ana avantajı, Compose paradigmasıyla tam uyumluluktur: composable(), FragmentManager veya işlemlere gerek kalmadan diğer Compose bileşenleriyle aynı yaşam döngüsünde çalışır. Bu, Fragment ve Compose yaşam döngüsü uyumsuzluğuyla ilgili bir hata sınıfını ortadan kaldırır.

Her composable(), bir dize rotası ve bir NavBackStackEntry nesnesi alıp Composable UI döndüren bir lambda fonksiyonu alır. Lambda içinde, kapsamdan navController aracılığıyla NavController'a erişilebilir ve diğer ekranlara navigasyon sağlanır. Bu mimari, navigasyonu açık ve öngörülebilir hale getirir.

kotlin
@Composable
fun AppNavigation() {
    val navController = rememberNavController()
    
    NavHost(
        navController = navController,
        startDestination = "home"
    ) {
        composable("home") {
            HomeScreen(
                onNavigateToProfile = {
                    navController.navigate("profile")
                }
            )
        }
        composable("profile") {
            ProfileScreen(
                onBack = { navController.popBackStack() }
            )
        }
    }
}

composable() nasıl çalışır: anahtarlar ve parametreler

composable() çağrılarının her biri, NavHost'un iç grafiğinde benzersiz bir rota tanımlayıcısına sahip bir köşe oluşturur. NavController navigate() işlemini yürüttüğünde, kütüphane istenen rotayı kayıtlı tüm composable köşelerle karşılaştırır ve bir eşleşme bulur. Eşleşmeden sonra bir NavBackStackEntry oluşturulur, navigasyon yığınına yerleştirilir ve UI kompozisyonu başlar.

composable()'ın dahili uygulaması bir geç başlatma mekanizması kullanır: ekran kompozisyonu yalnızca o rotaya ilk navigasyonda gerçekleşir. Bu, kullanıcının hiç gitmediği ekranların bellek kaplamadığı ve hiçbir kod çalıştırmadığı anlamına gelir. Bu yaklaşım, çok sayıda ekrana sahip uygulamalarda performansı önemli ölçüde artırır.

composable() içindeki key parametresi, ekranın yeniden oluşturulmasını yönetmeye olanak tanır. Varsayılan olarak, aynı rotaya tekrar tekrar gidildiğinde composable yeniden oluşturulmaz — NavHost mevcut geri yığın girdisini kullanır. Ancak, bir key iletilir ve değişirse, NavHost composable fonksiyonunun yeni bir örneğini oluşturur. Bu, yeniden açıldığında durumu zorla güncellemeniz gereken dinamik verilere sahip ekranlar için kullanışlıdır.

kotlin
val NavGraphBuilder.Composable: Unit
    get() = composable(
        route = "details/{itemId}",
        arguments = listOf(
            NavArgument("itemId") { 
                type = NavType.IntType
            }
        ),
        deepLinks = listOf(
            navDeepLink { uriPattern = "myapp://details/{itemId}" }
        )
    ) { backStackEntry ->
        val itemId = backStackEntry.arguments?.getInt("itemId") ?: 0
        DetailsScreen(itemId = itemId)
    }

composable() aracılığıyla argüman aktarma

composable(), arguments parametresi aracılığıyla esnek bir argüman sistemini destekler. Her argüman, türü, varsayılan değeri ve zorunluluğu tanımlayan bir NavArgument nesnesiyle tanımlanır. Argümanlar, rota içinde yol parametreleri (süslü parantezler aracılığıyla) veya sorgu parametreleri (soru işareti aracılığıyla) olarak iletilir.

Yol parametreleri doğrudan rota şablonunda belirtilir: "profile/{userId}". "profile/42"ye gidildiğinde, NavHost otomatik olarak 42 değerini çıkarır ve backStackEntry.arguments aracılığıyla erişilebilir hale getirir. Sorgu parametreleri soru işaretinden sonra eklenir: "search?query={text}" ve kütüphane tarafından otomatik olarak ayrıştırılır.

Argümanları çıkarırken, parametrenin zorunluluğunu NavType.isNullableAllowed aracılığıyla kontrol etmek ve NavArgument defaultValue aracılığıyla varsayılan değerler sağlamak önemlidir. Zorunlu bir parametre eksikse, Navigation Compose bir IllegalArgumentException fırlatarak yanlış rotalarla ilgili ince hataları önler.

Argüman türüNavTypeRotada örnek
IntNavType.IntType"item/{id}"
StringNavType.StringType"user/{name}"
BooleanNavType.BoolType"filter?enabled={value}"
FloatNavType.FloatType"map/{lat}/{lon}"
LongNavType.LongType"article/{timestamp}"

Karmaşık nesneleri aktarmak için NavType.ParcelableType veya NavType.SerializableType kullanılması önerilir. Ancak Google, aktarılan verilerin boyutunun en aza indirilmesini tavsiye eder — bir tanımlayıcı iletmek ve nesneyi ekran içinde kimliğe göre yüklemek daha iyidir. Bu, büyük serileştirilmiş verilerle ilgili sorunları önler ve yapılandırma değişikliklerinin işlenmesini basitleştirir.

kotlin
data class Profile(val id: Int, val name: String) : Parcelable

            // Minimum veriyle gezin
navController.navigate("profile/42")

            // Ekrandaki argümanları al
composable(
    route = "profile/{userId}",
    arguments = listOf(
        NavArgument("userId") { type = NavType.IntType }
    )
) { backStackEntry ->
    val userId = backStackEntry.arguments?.getInt("userId") ?: 0
    ProfileDetailScreen(userId = userId)
}

composable() ile iç içe navigasyon

Gerçek uygulamalarda, genellikle iç içe navigasyon grafikleri düzenlemek gerekir — örneğin, bir BottomNavigation sekmesi içinde ayrı bir ekran yığını. composable(), iç içe NavHost'lar aracılığıyla yerleştirmeyi destekler: bir composable ekranı içinde, bağımsız bir rota yığınına sahip kendi NavHost'unuzu bildirebilirsiniz.

Her iç içe NavHost, kendi NavController ve geri yığınına sahiptir. Bu, bir sekme içindeki navigasyonun diğer sekmelerdeki navigasyonu etkilemediği anlamına gelir — kullanıcı, her birinin içindeki gezinme geçmişini kaybetmeden sekmeler arasında özgürce geçiş yapabilir. Bu mimariye Scoped Navigation denir ve Google tarafından karmaşık çok düzeyli navigasyona sahip uygulamalar için önerilir.

İç içe navigasyon uygulanırken, NavController durumunun doğru yönetilmesi önemlidir: her iç içe NavHost, composable fonksiyonunun kapsamı içinde kendi rememberNavController'ını saklamalıdır. Android Developer Summit 2024'e göre, üç veya daha fazla sekmeye sahip Jetpack Compose uygulamalarının %40'ından fazlası, modüller arasındaki navigasyonu yalıtmak için iç içe NavHost mimarisini kullanır.

kotlin
// Sekmeli ana NavHost
composable("tabs") {
    MainTabsScreen { tab ->
        when (tab) {
            Tab.Home -> HomeNavGraph()
            Tab.Search -> SearchNavGraph()
        }
    }
}

// Ana Sayfa sekmesi içinde iç içe grafik
@Composable
fun HomeNavGraph() {
    val navController = rememberNavController()
    NavHost(
        navController = navController,
        startDestination = "home_feed"
    ) {
        composable("home_feed") { FeedScreen() }
        composable("home_detail/{postId}") { PostDetailScreen() }
    }
}

composable() vs Intent navigasyonu

Jetpack Compose'dan önce, Android'de standart navigasyon yöntemi Intent ve FragmentManager kullanıyordu. Intent, yeni bir Activity başlatan bir sistem mesajıdır ve tüm View ağacının yeniden oluşturulması anlamına gelir. Buna karşılık, composable() tek bir Activity içinde çalışır ve Compose ağacının yalnızca bir bölümünü değiştirir, bu da önemli ölçüde daha hızlı ve bellek açısından daha verimlidir.

composable() ile Intent tabanlı navigasyon arasındaki temel farklar:

  • Hız — composable(), Activity'yi yeniden oluşturmadan milisaniyeler içinde ekran değiştirir; Intent, Activity'nin yeniden başlatılmasını gerektirir.
  • Animasyonlar — Navigation Compose'da geçiş animasyonları, overridePendingTransition gerektirmeden AnimatedNavHost aracılığıyla bildirimsel olarak tanımlanır.
  • Paylaşılan durum — composable(), Intent extras olmadan ekranlar arasında veri aktarımını basitleştiren paylaşılan bir ViewModel kapsamında çalışır.
Özellikcomposable()Intent / Fragment
MimariTek Activity, Compose ağacıÇoklu Activity, Fragment yığınları
Veri aktarımıyol/sorgu parametreleri, paylaşılan ViewModelIntent extras, Bundle, SharedPreferences
Derin bağlantılarYerleşik navDeepLink desteğimanifest'te intent-filter
Geri yığınıOtomatik popBackStack yönetimiFragmentManager.popBackStack()
Değiştirme süresi5–15 ms (işlem içi)50–200 ms (yeniden oluşturmayla)

Intent'ten composable()'a geçiş, yalnızca bir API değişimi değil, mimari paradigma değişikliğidir. Hangi Activity'nin açılması gerektiğini açıkça belirtmek yerine, geliştirici tüm olası rotaları tek bir yerde bildirimsel olarak tanımlar, bu da kod okunabilirliğini artırır ve navigasyon testini basitleştirir. Google I/O 2024'e göre, Navigation Compose ile Jetpack Compose, FragmentManager'a kıyasla navigasyon kodunu %40–60 oranında azaltır.

composable() ile sık yapılan hatalar

En sık yapılan hatalardan biri, yeniden oluşturma sırasında NavController'ın yeniden oluşturulmasıdır. NavController, durum değişikliğinde yeniden oluşturulabilen üst composable düzeyinde rememberNavController() aracılığıyla oluşturulursa, navigasyon bozulur — geçmiş kaybolur. Doğru çözüm, NavController'ı kararlı bir composable düzeyine (Activity düzeyi veya uygulamanın kök composable'ı gibi) yükseltmektir.

İkinci yaygın sorun, navigasyon sırasında sonsuz yeniden oluşturmadır. Bu, navController.navigate() doğrudan bir composable fonksiyonunun gövdesine yerleştirildiğinde olur. Navigasyon NavHost'un durumunu değiştirdiğinden, yeniden oluşturmayı tetikler ve bu da tekrar navigate() çağrısına yol açarak bir döngü oluşturur. Tüm navigasyon çağrıları, lambda işleyicilerine (onClick, onButtonPressed) sarılmalı, oluşturma sırasında yürütülmemelidir.

Üçüncü hata, BottomNavigation kullanırken yanlış geri yığını işlemedir. Her sekme değişiminde navigate() aracılığıyla basit navigasyon, mevcut olana dönmek yerine yığına yeni bir giriş ekler. BottomNavigation için restoreState = true ve launchSingleTop = true ile navController.navigate() kullanmalısınız, bu da sekme değiştirirken durumun doğru şekilde geri yüklenmesini sağlar.

kotlin
fun NavController.navigateToTab(route: String) {
    navigate(route) {
        popUpTo(navController.graph.findStartDestination().id) {
            saveState = true
        }
        launchSingleTop = true
        restoreState = true
    }
}

Sıkça Sorulan Sorular

composable() ile normal bir @Composable fonksiyonu arasındaki fark nedir?

composable() bir notasyon değil, bir rotayı UI'ye bağlayan NavHost'un genişletme fonksiyonudur. Normal bir @Composable fonksiyonu yalnızca düzeni tanımlarken, composable() bu düzeni belirtilen bir rotayla navigasyon grafiğine kaydeder ve NavController aracılığıyla navigasyon için erişilebilir hale getirir.

composable() ekranları arasında karmaşık bir nesne nasıl aktarılır?

Yol parametresi aracılığıyla yalnızca bir tanımlayıcı (ID) iletilmesi ve nesnenin bir depo veya ViewModel aracılığıyla ekranda kimliğe göre yüklenmesi önerilir. Yine de nesneyi aktarmanız gerekiyorsa, NavType.ParcelableType kullanın, ancak 1 KB'den büyük nesneleri aktarmaktan kaçının — bu TransactionTooLargeException'a yol açabilir.

Ekran döndürüldüğünde composable() ekranı neden yeniden oluşturulur?

Ekran döndürme, varsayılan olarak Activity'yi yeniden oluşturan bir yapılandırma değişikliğine neden olur. Composable ekranlarının durumunu korumak için basit veriler için rememberSaveable veya o ekranın kapsamına sahip ViewModel kullanın. Navigation Compose, yeniden oluşturma sonrasında geri yığınını geri yükler, ancak composable() fonksiyonları içindeki durum rememberSaveable olmadan sıfırlanır.

composable() NavHost olmadan kullanılabilir mi?

Hayır, composable(), yalnızca NavHost bloğu içinde kullanılabilen NavGraphBuilder'ın bir genişletme fonksiyonudur. Navigasyon olmadan basit UI değişimi için koşullu oluşturma (when, if) veya AnimatedContent kullanın. composable() özellikle geri yığını ve derin bağlantı desteğiyle yönlendirme için tasarlanmıştır.

composable()'da ilk navigasyonu geri navigasyondan nasıl ayırt edebilirim?

ViewModel içinde SavedStateHandle kullanın: ilk navigasyonda handle.get("initialized") null döndürür; geri navigasyonda kaydedilen değeri döndürür. Alternatif olarak, navController.previousBackStackEntry aracılığıyla geri yığınındaki mevcut konumu analiz edin — null ise, bu navigasyon yığınındaki ilk ekrandır.

Özet

  • composable(), NavHost'ta ekran kayıt fonksiyonudur, Jetpack Compose'da navigasyonu düzenlemenin ana yoludur.
  • Rotalar — her ekran, isteğe bağlı yol ve sorgu parametreleriyle bir rota dizesiyle tanımlanır.
  • Argümanlar — ilkel, Parcelable ve Serializable türleri desteğiyle NavArgument aracılığıyla iletilir.
  • İç içe yerleştirme — composable(), bağımsız yığınlarla modüler navigasyon düzenlemek için iç içe NavHost'ları destekler.
  • Performans — geç ekran başlatma bellekten tasarruf sağlar, ekran değiştirme hızı 5–15 ms'dir.
  • Hatalar — ana sorunlar: NavController yeniden oluşturma, composable gövdesinde navigate() ile sonsuz yeniden oluşturma, yanlış BottomNavigation işleme.
  • Geçiş — FragmentManager'dan composable()'a geçiş, navigasyon kodu hacmini %40–60 oranında azaltır ve Fragment yaşam döngüsüyle ilgili bir hata sınıfını ortadan kaldırır.

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