---
title: 'Derin Bağlantılar ve Kısayollar'
source: 'https://academia.sh/tr/kurslar/android-servisler/derin-baglantilar-ve-kisayollar'
course: 'Platform Servisleri ve Tümleştirmeler'
language: tr
updated: '2026-10-21T05:02:41+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Derin bağlantı, doğrulanmış uygulama bağlantısı ve kısayolun görevlerini ayırır'
    - 'Ekran yeniden oluşturulurken aynı derin bağlantının iki kez işlendiğini ölçer'
    - 'İşlendi işaretinin kaydedilmiş durumda tutulduğunda bağlantıların birebir ulaştığını gösterir'
    - 'İşaret bellekte tutulursa süreç sonlandıktan sonra bağlantının yine yinelendiğini gösterir'
---

# Derin Bağlantılar ve Kısayollar

Derin bağlantı dışarıdan gelen bir adresi uygulamanın belirli bir ekranına bağlar; ekran yeniden oluşturulurken aynı bağlantı bir daha işlenebilir. Ders bu yinelenen teslimi ve işlendi işaretinin kaydedilmiş durumda ya da bellekte tutulmasının sonucunu ölçer.

Önceki derste alıcı yetişemeyince okumalar atlanıyordu. Derin bağlantıda sorun ters yönden çıkar: bir bağlantı alıcıya bir kez gelir, ama alıcı onu bir kez daha işleyebilir. Kullanıcı bir e-postadaki adrese dokunur, uygulama ilgili ürün ekranını açar. Ekran döndürüldüğünde ekran yeniden oluşturulur ve aynı bağlantı bir daha işlenirse kullanıcı ürün ekranını ikinci kez açılmış görür. Bu derste de aynı soruyu soruyoruz: **gönderilen bu olay alıcıya kaç kopya olarak ulaştı?**

```kotlin
// Arrival.kt — gonderilen bir olayin aliciya kac kopya olarak ulastigini siniflandirir
class Signal(val key: String, val seq: Int)

class Arrival(val label: String, val sent: Signal, received: List<Signal>) {
    val copies: Int = received.count { it.seq == sent.seq }
    val verdict: String = when {
        copies > 1 -> "yinelenen"
        copies == 1 -> "birebir"
        received.any { it.key == sent.key && it.seq > sent.seq } -> "ezilen"
        else -> "kayip"
    }

    fun line() {
        println("$label: anahtar=${sent.key} | kopya=$copies -> $verdict")
    }
}

fun countArrivals(arrivals: List<Arrival>) {
    for (name in listOf("birebir", "yinelenen", "ezilen", "kayip")) {
        println("$name: ${arrivals.count { it.verdict == name }}")
    }
}
```

Sınıflandırma önceki derslerdekiyle aynıdır. Kural alıcının listesinde aynı sırayı taşıyan kopyaları sayar; hiç kopya yoksa aynı anahtarla daha sonraki bir olayın ulaşıp ulaşmadığına bakar. İçeriği ve nedeni görmez.

## Derin Bağlantı ve Kısayol

Derin bağlantı, bir adresin uygulamanın belirli bir ekranını açmasını sağlar. Uygulama bildirim dosyasında hangi adreslerle açılacağını bir `intent` süzgeciyle tanımlar. Doğrulanmış uygulama bağlantısı bir adım ileri gider: adresin sahibi alanı uygulamaya bağladığını doğrular ve platform bağlantıyı kullanıcıya sormadan uygulamaya verir. Kısayol ise uygulama simgesine uzun basınca çıkan, belirli bir ekrana giden bir kayıttır; o da bir `intent` taşır.

```xml
<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="ornek.example" android:pathPrefix="/urun" />
</intent-filter>
```

Bağlantı uygulamaya bir `intent` olarak gelir ve ekran onu açılışta okur.

```kotlin
// Platform kodu: ProductActivity
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class ProductActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val link = intent?.data
        if (link != null) openProduct(link.lastPathSegment)
    }
}
```

`onCreate` ekran her yeniden oluşturulduğunda çalışır ve `intent` aynı kalır. Bu parça çıktı ya da süre iddia etmez. Model, platformun bu kuralını kurar; model platformun kendisi değildir.

## Yeniden İşlenen Bağlantı

Modelde her bağlantı bir `Signal`dır ve anahtarı ürün adresidir. Ekran yeniden oluşturulunca aynı bağlantı bir daha işlenir; bu, aynı sıranın ikinci kez ulaşmasıdır. Modelde yeniden işleme, belirtilen sıraların listenin sonuna bir kopya olarak eklenmesidir.

```kotlin
// Redeliver.kt — ekran yeniden olusturulunca ayni baglantiyi bir kez daha verir
fun redeliver(sent: List<Signal>, again: List<Int>): List<Signal> =
    sent + again.map { seq -> sent.first { it.seq == seq } }
```

```kotlin
// Main.kt — ekran yeniden olusturulunca iki baglanti iki kez islenir
fun main() {
    val sent = listOf(
        Signal("urun.7", 1),
        Signal("urun.9", 2),
        Signal("urun.12", 3),
        Signal("urun.15", 4),
    )
    val received = redeliver(sent, again = listOf(2, 3))
    val arrivals = sent.map { Arrival("olay-${it.seq}", it, received) }
    arrivals.forEach { it.line() }
    countArrivals(arrivals)
}
```

```text
olay-1: anahtar=urun.7 | kopya=1 -> birebir
olay-2: anahtar=urun.9 | kopya=2 -> yinelenen
olay-3: anahtar=urun.12 | kopya=2 -> yinelenen
olay-4: anahtar=urun.15 | kopya=1 -> birebir
birebir: 2
yinelenen: 2
ezilen: 0
kayip: 0
```

Bu dersin teslimi **yinelenen**dir. 2 ve 3 numaralı bağlantılar iki kopya olarak ulaştı; 1 ve 4 numaralı bağlantılar tek kopya ile birebir kaldı. Kullanıcı ürün sayfasının iki kez açıldığını görür. Kural, kopyanın döndürmeden mi yoksa başka bir nedenden mi geldiğini görmez.

**SY1.** Model, yeniden işlemeyi listenin sonuna eklenen bir kopya olarak kurar. Platformda ekran yeniden oluşturulduğunda aynı `intent` ekranın kendi akışı içinde tekrar okunur ve kopyanın tam olarak ne zaman geleceği ekranın yaşam döngüsüne bağlıdır; bu modelde yoktur.

## Açık Ekrana Yeni Bağlantı

Kullanıcı uygulama açıkken ikinci bir bağlantıya dokunursa platform iki yoldan birini seçer: ekranı yeniden oluşturur ya da var olan ekrana yeni bağlantıyı ayrı bir çağrıyla verir. Ekranın açılış kipi hangisinin seçileceğini belirler. Yeniden oluşturma, ekranın yaşam döngüsünü baştan başlatır ve bağlantı bu sırada açılışta okunur. Var olan ekrana verme ise yeni bağlantıyı ayrı bir geri çağrıyla iletir ve açılışta okunan bağlantıya dokunmaz.

Bu ikilik yinelenmenin bir kaynağıdır. Açılış kipi her seferinde yeni ekran üretiyorsa, eski ekran arka yığında kalır ve geri tuşuna basıldığında eski ekran, hâlâ elinde tuttuğu bağlantıyla yeniden görünür. Kullanıcı aynı ürünü ikinci kez açılmış görür. Hangi kipin seçildiği uygulamanın tercihidir; ölçüm yalnız sonucunu, yani kaç kopyanın işlendiğini sayar.

## İşlendi İşareti

Yinelenmeyi önlemenin yolu, bağlantının işlendiğini bir işaretle tutmaktır. İşaret kaydedilmiş durumda tutulursa, ekran yeniden oluşturulsa bile bir sonraki okumada bağlantının işlendiği bilinir. Tekilleştirme (deduplication) böyle çalışır: aynı sıra ikinci kez gelirse işlenmez.

```kotlin
// Handled.kt — islendi isareti tutulursa daha once islenen baglantiyi atlar
fun dedupe(arrived: List<Signal>, kept: Boolean, restartAt: Int): List<Signal> {
    val handled = mutableSetOf<Int>()
    val processed = mutableListOf<Signal>()
    arrived.forEachIndexed { i, s ->
        if (i == restartAt && !kept) handled.clear()
        if (handled.add(s.seq)) processed.add(s)
    }
    return processed
}
```

`kept` işaretin süreç yeniden başlasa da korunup korunmadığını, `restartAt` sürecin hangi gelişten önce yeniden başladığını gösterir.

```kotlin
// Main.kt — islendi isareti kaydedilmis durumda tutulursa baglantilar birebir ulasir
fun main() {
    val sent = (5..8).map { Signal("urun.${it * 2}", it) }
    val arrived = redeliver(sent, again = listOf(6, 7))
    val received = dedupe(arrived, kept = true, restartAt = 4)
    val arrivals = sent.map { Arrival("olay-${it.seq}", it, received) }
    arrivals.forEach { it.line() }
    countArrivals(arrivals)
}
```

```text
olay-5: anahtar=urun.10 | kopya=1 -> birebir
olay-6: anahtar=urun.12 | kopya=1 -> birebir
olay-7: anahtar=urun.14 | kopya=1 -> birebir
olay-8: anahtar=urun.16 | kopya=1 -> birebir
birebir: 4
yinelenen: 0
ezilen: 0
kayip: 0
```

Aynı iki yeniden işleme tekilleştirmeden geçti ve dört bağlantının dördü birebir ulaştı. İşlenen liste tek kopya taşır.

**SY2.** Model, işareti saklamanın bedelini sıfır kabul eder. Platformda kaydedilmiş duruma yazılan veri sınırlıdır ve işaretin ne kadar saklanacağı uygulamanın kararıdır; bu modelde yoktur.

## Kısayollar

Kısayol üç biçimde bulunur. Statik kısayol uygulamayla birlikte gelir ve kaynak dosyasında tanımlıdır; uygulama güncellenene kadar değişmez. Dinamik kısayolu uygulama çalışırken kendisi ekler, günceller ve siler; uygulama verisi temizlendiğinde dinamik kısayollar da silinir. Sabitlenmiş kısayolu kullanıcı ana ekrana yerleştirir; uygulamanın bu kısayolu kaldırması mümkün değildir, yalnız pasifleştirebilir.

Kısayolun teslimle ilgili tarafı hedefidir. Kısayol, bağlantı gibi bir `intent` taşır ve aynı ekran aynı biçimde açar. Bu yüzden derin bağlantı için kurulan tekilleştirme kısayol için de geçerlidir: ekran yeniden oluşturulduğunda kısayolun hedefi de yeniden okunur. Fark, kısayolun kullanıcı tarafından değil uygulama tarafından tanımlanmasıdır. Kaldırılmış bir kısayola dokunan kullanıcı, bağlantıya dokunan kullanıcıdan farklı bir hata görür: bağlantı hiç açılmaz, kısayol ise açıldığı halde hedef ekran bulunamaz.

## Bağlantı Türleri ve Doğrulama

Uygulamayı açan adresler üç türe ayrılır. Özel şemalı bir adres yalnızca uygulamanın tanımladığı bir önek taşır ve herhangi bir uygulama aynı öneki tanımlayabilir. Bir adresi birden çok uygulama tanıyorsa platform kullanıcıya hangisiyle açacağını sorar. Web adresli bağlantıda aynı soru tarayıcıyla uygulama arasında yaşanır. Doğrulanmış uygulama bağlantısı bu soruyu ortadan kaldırır: adresin sahibi, alanındaki bir dosyayla uygulamanın kimliğini bağladığını bildirir ve platform bağlantıyı doğrudan o uygulamaya verir.

Doğrulama başarısız olursa platform bağlantıyı uygulamaya vermez. Uygulama hata görmez; bağlantı tarayıcıda ya da seçim ekranında açılır. Kullanıcı bir ürün bağlantısına dokunur ve uygulamanın ürün sayfası yerine web sayfasını görür. Bu, teslimin görünmez bir kaybıdır: uygulama için olay hiç gönderilmemiş gibi görünür, kullanıcı için ise gönderilen bir eylem sonuçsuz kalmıştır.

Modelde doğrulama, belirli bir alana ait bağlantıların hepsini uygulamadan geri tutar. Alan anahtarın ilk parçasıdır ve doğrulanmamış alan modelin uydurma bir değeridir.

```kotlin
// Verify.kt — dogrulanmamis alana ait baglantilari uygulamaya vermez
fun verifiedOnly(sent: List<Signal>, unverified: String): List<Signal> =
    sent.filter { !it.key.startsWith("$unverified.") }
```

```kotlin
// Main.kt — dogrulanmamis alanin baglantilari uygulamaya ulasmaz
fun main() {
    val sent = listOf(
        Signal("ornek.urun7", 13),
        Signal("eski.urun3", 14),
        Signal("ornek.urun9", 15),
        Signal("eski.urun3", 16),
    )
    val received = verifiedOnly(sent, unverified = "eski")
    println("ulasan siralar: ${received.map { it.seq }}")

    val arrivals = sent.map { Arrival("olay-${it.seq}", it, received) }
    arrivals.forEach { it.line() }
    countArrivals(arrivals)
}
```

```text
ulasan siralar: [13, 15]
olay-13: anahtar=ornek.urun7 | kopya=1 -> birebir
olay-14: anahtar=eski.urun3 | kopya=0 -> kayip
olay-15: anahtar=ornek.urun9 | kopya=1 -> birebir
olay-16: anahtar=eski.urun3 | kopya=0 -> kayip
birebir: 2
yinelenen: 0
ezilen: 0
kayip: 2
```

Doğrulanmış alanın iki bağlantısı birebir ulaştı. Doğrulanmamış alanın iki bağlantısı ulaşmadı ve ardından aynı anahtarla bir bağlantı gelmediği için kayıp oldu. Aynı adres iki kez gönderildiği halde, bu kez yinelenen sayılmadı: yinelenen, ulaşan kopyaların sayısıdır, gönderilen kopyaların değil.

**SY3.** Model, doğrulamayı alan bazında hepsi ya da hiçbiri olarak kurar. Platformda doğrulama alan dosyasının indirilmesine, uygulama imzasına ve yol önekine bağlıdır ve kısmi doğrulama da mümkündür; bunlar modelde yoktur.

## Soğuk Başlangıç ve Bağlantı Verisi

Bağlantı uygulamayı iki ayrı durumda bulabilir. Uygulama hiç çalışmıyorsa süreç sıfırdan başlar, ekran oluşturulur ve bağlantı açılış sırasında okunur. Uygulama arka plandaysa süreç yaşıyordur ve ekran ya yeniden oluşturulur ya da var olan ekrana yeni bağlantı verilir. İşlendi işaretinin ikinci duruma yardımı büyüktür; ilk durumda ise işaret henüz yoktur ve bağlantı tek kopya olarak gelir.

Bağlantıdan gelen veri dış dünyadan gelir ve güvenilir değildir. Adresin son parçası bir ürün numarasıysa, uygulama onu sayıya çevirmeden önce biçimini denetlemelidir; olmayan ya da geçersiz bir ürün için hata ekranı göstermelidir. Teslim açısından bu denetim, kopyaları değil içeriği ilgilendirir ve ölçümün dışında kalır. Kural bağlantının ulaştığını sayar; ulaşan bağlantının geçerli olup olmadığına bakmaz. Geçersiz bir bağlantı birebir ulaşabilir ve yine de kullanıcıya bir ürün göstermeyebilir.

## Geri Tuşu ve Ekran Yığını

Bağlantı uygulamayı doğrudan iç bir ekrana açtığında, kullanıcının geri tuşuna bastığında nereye gideceği bir tasarım sorusudur. Uygulama çalışmıyorsa ve yığında yalnızca ürün ekranı varsa, geri tuşu kullanıcıyı uygulamadan çıkarır. Uygulama ürün ekranının altına ana ekranı da yerleştirirse kullanıcı uygulamanın içinde kalır. Bu seçim teslimi değiştirmez, ama yinelenmeyi görünür kılar: yığında iki ürün ekranı varsa geri tuşu ilkini gösterir ve kullanıcı aynı ürünü ikinci kez görür. Kural bu iki ekranı yine tek bir kopya olarak ya da iki kopya olarak sayar; hangisi olduğu, bağlantının kaç kez işlendiğine bağlıdır.

## Yaygın Yanılgılar

**"Doğrulanmış bağlantı her zaman uygulamayı açar."** Doğrulama başarılıysa açar. Başarısız ya da henüz tamamlanmamış doğrulamada bağlantı tarayıcıya gider. Uygulama bunu hata olarak görmez, çünkü kendisine hiçbir olay gönderilmemiştir.

**"Aynı bağlantı iki kez geldiyse platform hata yapmıştır."** Platform bağlantıyı bir kez verir. İkinci kopya, ekranın yeniden oluşturulmasından ve açılışta bağlantının yeniden okunmasından gelir. Kaynak platformun değil, ekranın yaşam döngüsüdür.

**"İşlendi işareti yalnız bellekte tutulabilir."** Bellekteki işaret döndürmeye karşı korur, süreç sonlandırıldığında yok olur. Ölçümde fark yalnız `kept` değeriydi ve bedeli iki yinelenen bağlantıydı. İşaret kaydedilmiş durumda ya da kalıcı bir depoda tutulmalıdır.

**"Tekilleştirme kayıp riskini artırır."** Tekilleştirme yalnız aynı sırayı ikinci kez işlemez. Farklı sıralı bağlantıları bir diğerinin yerine koymaz. Yanlış anahtarla tekilleştirme ise farklı iki ürünü aynı sayar ve ilkinden sonra ikincisini atar; bu, ezilen değil, uygulama hatası kaynaklı kayıptır.

**"Kısayol ile bağlantı aynı şeydir."** İkisi de bir `intent` taşır, ama sahipleri farklıdır. Bağlantıyı dışarıdan biri üretir ve uygulama içeriğini denetlemek zorundadır; kısayolu uygulamanın kendisi tanımlar ve içeriğine daha çok güvenebilir. Yinelenme açısından ikisi aynı davranır.

**"Yinelenen bağlantı zararsızdır."** Ürün ekranını iki kez açmak yalnızca görsel bir kusurdur; ama bağlantı bir ödeme ya da onay işlemini tetikliyorsa ikinci kopya ikinci işlemdir ve geri alınması zordur.

## Sınırlayıcı Ölçüm

İşaret yalnız bellekte tutulursa, süreç sonlandırıldığında bellek silinir. Sistem bellek baskısıyla uygulamayı arka planda sonlandırabilir ve kullanıcı geri döndüğünde ekran yeniden oluşturulur. Bellekteki işaret kaybolduğu için aynı bağlantı yine işlenir.

```kotlin
// Main.kt — isaret bellekte tutulursa surec sonlaninca baglanti yine yinelenir
fun main() {
    val sent = (9..12).map { Signal("urun.${it * 2}", it) }
    val arrived = redeliver(sent, again = listOf(10, 11))
    val received = dedupe(arrived, kept = false, restartAt = 4)
    val arrivals = sent.map { Arrival("olay-${it.seq}", it, received) }
    arrivals.forEach { it.line() }
    countArrivals(arrivals)
}
```

```text
olay-9: anahtar=urun.18 | kopya=1 -> birebir
olay-10: anahtar=urun.20 | kopya=2 -> yinelenen
olay-11: anahtar=urun.22 | kopya=2 -> yinelenen
olay-12: anahtar=urun.24 | kopya=1 -> birebir
birebir: 2
yinelenen: 2
ezilen: 0
kayip: 0
```

Girdi bir önceki ölçümle aynıdır, ama işaret bellekte kaldığı için 10 ve 11 numaralı bağlantılar yeniden başlatma sonrasında yine işlendi ve yinelenen oldu. Fark yalnız `kept` değerindedir. Bellekte tutulan işaret döndürmeye karşı korur, süreç sonlanmasına karşı korumaz.

**SY4.** Model, sürecin sonlanmasını tek bir noktada kurar. Platformda sonlanma her an olabilir ve kaydedilmiş durumun geri yüklenmesi sonlanma türüne göre değişir; bunlar modelde yoktur.

## Özet

- Bu dersin teslimi: yinelenen. Ekran yeniden oluşturulunca aynı derin bağlantı iki kez işlenir.
- Dört bağlantıdan ikisi iki kopya olarak ulaştı: yinelenen 2, birebir 2.
- İşlendi işareti kaydedilmiş durumda tutulduğunda dört bağlantının dördü birebir ulaştı.
- İşaret bellekte tutulduğunda süreç sonlandıktan sonra iki bağlantı yine yinelenen oldu: yinelenen 2.
- Doğrulanmamış alanın iki bağlantısı uygulamaya ulaşmadı: birebir 2, kayip 2. Uygulama bunu hata olarak görmez.
- Doğrulanmış uygulama bağlantısı adresin sahibinin uygulamaya bağladığını doğrular; kısayol bir ekrana giden `intent` taşır.

## Sonraki Adım

Bu derste olay dışarıdan geldi ve aynı olay iki kez işlendi. Pencere öğesinde olay ana ekrandaki küçük bir görünümü güncellemektir ve görünüm hiç yoksa güncelleme alıcı bulamaz. Sıradaki ders, `Pencere Öğeleri`, pencere açılınca çizilen son güncellemeyi ve ana ekrandan kaldırılmış pencere öğesini ölçer.
