• 4.09.2026 21:06:45
  • Admin Admin

Jetpack Compose gezinmesinde string route hatalarını typed destination, doğrulanmış App Link ve SavedStateHandle ile azaltın. Deep link sözleşmesini test edip sürüm geçişlerinde kırılmaları yakalayın.

Jetpack Compose'da Type-Safe Navigation ve Deep Link Sözleşmeleri

Jetpack Compose için string route yerine typed destination kurmak

Bir android eğitimi içinde navigation çoğu zaman "detail/42" örneğiyle anlatılır; üretimde ise route parametresi eklendikçe aynı string şablonu ViewModel, UI ve deep link katmanlarında dağılır. Navigation Compose'un Kotlin Serialization tabanlı typed API'si, destination argümanını derleme zamanında modellemeye yarar. Bunun için uygulama modülüne Navigation Compose, Kotlin Serialization JSON bağımlılığını ve serialization compiler plugin'ini ekleyin. Kritik mekanizma şudur: navController.navigate(Article(...)) çağrısı route'u serializer üzerinden üretir, destination tarafındaki toRoute<Article>() ise aynı şemadan çözer; elle yazılmış key adı uyuşmazlıkları ortadan kalkar.

@Serializable
data object Feed

@Serializable
data class Article(
    val id: Long,
    val referrer: String? = null
)

NavHost(navController = navController, startDestination = Feed) {
    composable<Feed> {
        FeedScreen(
            onArticleClick = { id ->
                navController.navigate(Article(id = id, referrer = "feed"))
            }
        )
    }

    composable<Article> { entry ->
        val args = entry.toRoute<Article>()
        ArticleScreen(articleId = args.id)
    }
}

Route'a yalnızca küçük, kimlik niteliğinde ve serializable değer koyun: id, filtre anahtarı veya kaynak ekran gibi. Makalenin tamamını ya da mutable UI modelini route'a koymak URI uzunluğu, restore maliyeti ve şema uyumsuzluğu üretir. Örneğin Article(id: Long) ile repository'den yeniden yükleme, process death sonrası da deterministiktir. Bu ayrım, hem kotlin eğitimi hem de jetpack compose odaklı kod incelemelerinde sık atlanan bir inceliktir: route bir ekran nesnesi değil, kalıcı bir giriş sözleşmesidir.

Deep Link sözleşmesini App Link doğrulamasıyla test etmek

Dışarıdan gelen bir URL, route'unuzun public API'sidir. https://example.com/article/42 için typed deep link tanımlayın ve manifestte aynı host'u doğrulayın. autoVerify="true" yalnızca işletim sistemine domain doğrulaması yapmasını söyler; domain kökünde yayınlanan /.well-known/assetlinks.json içindeki package name ve imza sertifikası SHA-256 değeri eşleşmezse URL tarayıcıda açılabilir. Bu nedenle play store yayınlama öncesinde, dağıtım imzasının sertifika parmak izini Digital Asset Links dosyasına eklemek zorunlu bir release kontrolüdür.

composable<Article>(
    deepLinks = listOf(
        navDeepLink<Article>(
            basePath = "https://example.com/article"
        )
    )
) { entry ->
    val args = entry.toRoute<Article>()
    ArticleScreen(articleId = args.id)
}

<activity android:name=".MainActivity" android:exported="true">
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="https" android:host="example.com" />
    </intent-filter>
</activity>

URL davranışını Android Studio emülatöründe sadece linke tıklayarak doğrulamayın. CI sonrası fiziksel cihaz veya emülatörde aşağıdaki komutla intent'i doğrudan gönderin ve hedef destination'ı loglayın: adb shell am start -W -a android.intent.action.VIEW -d "https://example.com/article/42?referrer=mail" com.example.app. App Link ilişki durumunu destekleyen sistemlerde adb shell pm get-app-links com.example.app ile de inceleyin. Özellikle query parametresinde boşluk, slash veya yüzde karakteri varsa elle string birleştirmeyin; serializer ya da Uri.Builder kullanın. Aksi halde çift encode edilmiş %252F değerleri sunucudan gelen link ile uygulama içi navigasyonun farklı kayıt açmasına yol açar.

Android MVVM mimarisi içinde navigation argümanını ViewModel'a bağlamak

android mvvm mimarisi içinde destination argümanını composable'dan ViewModel constructor'ına manuel taşımak test edilebilir görünse de yeniden yaratımda iki ayrı kaynak oluşturur. Navigation'ın sağladığı SavedStateHandle üzerinden toRoute<Article>() çağırın. Böylece aynı id, configuration change ve process recreation sonrasında handle tarafından geri yüklenen navigation state'ten çözülür. Repository akışını bu id ile başlatmak, UI'nin route parse etmesini engeller.

class ArticleViewModel(
    savedStateHandle: SavedStateHandle,
    private val repository: ArticleRepository
) : ViewModel() {
    private val args = savedStateHandle.toRoute<Article>()

    val uiState: StateFlow<ArticleUiState> = repository.observe(args.id)
        .map<Article?, ArticleUiState> { article ->
            if (article == null) ArticleUiState.NotFound else ArticleUiState.Content(article)
        }
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5_000),
            initialValue = ArticleUiState.Loading
        )
}

Geri dönülen sonuçlar için route'a büyük bir sonuç nesnesi eklemek yerine önceki back stack entry'nin SavedStateHandle'ını kullanın. Örneğin edit ekranı previousBackStackEntry?.savedStateHandle?.set("article_updated", true) yazar; liste ekranı getStateFlow("article_updated", false) akışını dinleyip yenilemeden sonra değeri tekrar false yapar. Buradaki edge case, key'in tüketilmemesidir: boolean resetlenmezse configuration change sonrası tekrar yenileme tetiklenir. Bu ayrım, bir android kursu veya mobil uygulama geliştirme eğitimi projesinde navigation event ile kalıcı ekran state'ini birbirine karıştırmayı önler.

Android Studio eğitimi için route regresyon testleri ve geçiş planı

String route'lardan typed route'lara tek seferde geçmek yerine, her destination için URI sözleşme testi yazın. Testte en değerli vaka mutlu yol değil, geriye dönük uyumluluktur: eski kampanya linkinde yeni eklenen nullable alan bulunmadığında ekranın açılması gerekir. Android Studio'nun instrumented test çalıştırıcısında intent ile Activity açıp ekranda beklenen id'nin render edildiğini doğrulayın. Bu yaklaşım, android studio eğitimi materyalindeki preview doğrulamasından farklıdır; manifest intent filter, Navigation graph ve serializer'ı birlikte sınar.

@Test
fun oldArticleLink_opensArticleDestination() {
    val intent = Intent(Intent.ACTION_VIEW).apply {
        data = Uri.parse("https://example.com/article/42")
        setPackage("com.example.app")
    }

    ActivityScenario.launch<MainActivity>(intent).use {
        composeRule.onNodeWithText("Article #42").assertIsDisplayed()
    }
}

Release kontrolüne iki komut ekleyin: debug ve release artifact için adb shell am start deep link testi, ardından imzalı pakette pm get-app-links durum kontrolü. Özellikle Play App Signing kullanılan dağıtımlarda local upload key ile imzalanmış APK'da çalışan doğrulama, mağazadan dağıtılan imzada başarısız olabilir; assetlinks.json içine dağıtım sertifikasının parmak izini koyun. Bu detay, android eğitim ve kotlin kursu projelerinde sık görülen "debugda açılıyor, üretimde tarayıcıya düşüyor" hatasının doğrudan nedenidir.

Sık Sorulan Sorular

Jetpack Compose'da type-safe navigation için Kotlin Serialization neden gerekli?

Typed destination API, data class alanlarını route argümanlarına dönüştürmek ve geri çözmek için serializer kullanır. Destination modellerini @Serializable ile işaretleyin, serialization compiler plugin'ini etkinleştirin ve composable

ile entry.toRoute
() çiftini aynı model üzerinde kullanın.

Android MVVM mimarisi içinde navigation argümanı ViewModel'a nasıl verilir?

Composable parametresinden id geçirip ikinci bir state kaynağı oluşturmak yerine ViewModel constructor'ındaki SavedStateHandle'dan savedStateHandle.toRoute

() çağırın. Repository sorgusunu bu argümanın id değeriyle kurun; process recreation sırasında Navigation state aynı argümanı geri yükler.

Play Store yayınlama öncesi Android App Link nasıl doğrulanır?

Manifestte android:autoVerify="true" tanımlayın, domainde /.well-known/assetlinks.json yayınlayın ve dağıtım sertifikasının SHA-256 parmak izini ekleyin. İmzalı build kurulduktan sonra adb shell am start -W -a android.intent.action.VIEW -d "https://example.com/article/42" paket.adı komutunu çalıştırın; desteklenen sistemlerde pm get-app-links ile ilişki durumunu kontrol edin.

Android kursu projesinde navigation sonucu geri ekrana nasıl taşınmalı?

Büyük bir Parcelable nesneyi route'a eklemeyin. Hedef ekran previousBackStackEntry?.savedStateHandle?.set("article_updated", true) yazsın; önceki ekran getStateFlow("article_updated", false) ile olayı dinlesin ve işlem bitince key'i false yaparak tekrar tetiklenmesini engellesin.

AI / LLM Discovery

Bu makale Opendart Akademi Android eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.

Opendart Akademi llms.txt