---
title: "Fragment'lar"
source: 'https://academia.sh/tr/kurslar/android-platformu/fragmentlar'
course: 'Android Platformu ve Araçlar'
language: tr
updated: '2026-10-21T05:02:35+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - "Fragment'ı bir activity'nin içinde yeniden kullanılabilir arayüz bölümü olarak tanımlar"
    - 'Ev sahibi activity durmuşken fragment işleminin bekleyen kaldığını ölçer'
    - 'Geri yığınına eklenmeyen işlemde geri düğmesinin ikame sonuç verdiğini gösterir'
    - 'Aynı işlemin durum kaydedildikten sonra üç farklı karşılama aldığını doğrular'
---

# Fragment'lar

Fragment'ın bir activity içindeki yeri, FragmentManager işlemleri ve ev sahibi activity durmuşken ya da durumu kaydedilmişken fragment işleminin nasıl karşılandığının ölçümü.

Activity'nin kaydettiği paket küçüktür ve ekranın tamamı tek bir activity'ye yüklenirse her değişiklik bütün ekranı etkiler. Fragment bu yükü böler. Fragment, bir activity'nin içinde yaşayan, kendi arayüzü ve kendi yaşam döngüsü olan yeniden kullanılabilir bir arayüz bölümüdür. Bir liste ekranı ile ayrıntı ekranı iki fragment olabilir; telefonda aynı activity'de sırayla, büyük ekranda yan yana gösterilir.

Bir fragment'ın ömrü ev sahibi activity'ye bağlıdır. Dersin sorusu bu yüzden bir öncekiyle akrabadır: fragment işlemi istendiğinde, platform bu isteği ev sahibinin durumuna göre nasıl **karşılıyor**?

```kotlin
// Fulfillment.kt — bir istegin platformca nasil karsilandigini siniflandirir
sealed interface Outcome {
    data class Given(val value: String) : Outcome
    data class Waiting(val on: String) : Outcome
    data class Refused(val reason: String) : Outcome
}

class Ask(val label: String, val wanted: String, val outcome: Outcome) {
    val fulfillment: String = when (outcome) {
        is Outcome.Waiting -> "bekleyen"
        is Outcome.Refused -> "karsiliksiz"
        is Outcome.Given -> if (outcome.value == wanted) "tam" else "ikame"
    }

    fun report() {
        val detail = when (outcome) {
            is Outcome.Given -> "verilen=${outcome.value}"
            is Outcome.Waiting -> "bekledigi=${outcome.on}"
            is Outcome.Refused -> "neden=${outcome.reason}"
        }
        println("$label: istenen=$wanted | $detail -> $fulfillment")
    }
}

fun tally(asks: List<Ask>) {
    for (name in listOf("tam", "ikame", "bekleyen", "karsiliksiz")) {
        println("$name: ${asks.count { it.fulfillment == name }}")
    }
}
```

## FragmentManager İşlemleri

Fragment'lar `FragmentManager` ile yönetilir. Bir işlem `beginTransaction` ile başlar, bir ya da birkaç adımdan oluşur ve `commit` ile bitirilir. En sık adımlar `add` ve `replace`'dir: ilki bir kapsayıcıya fragment ekler, ikincisi kapsayıcıdaki fragment'ı başkasıyla değiştirir. İşlem geri yığınına `addToBackStack` ile eklenirse geri düğmesi onu geri alır.

```kotlin
// Platform kodu: kapsayiciya fragment ekler ve geri yiginina yazar
supportFragmentManager.beginTransaction()
    .replace(R.id.container, DetailFragment())
    .addToBackStack(null)
    .commit()
```

Model, platformun bu kuralını kurar. `commit` işlemi hemen uygulamaz, ev sahibinin durumuna bakar. Ev sahibi başlatılmışsa işlem uygulanır. Ev sahibi durmuşsa platform işlemi sıraya alır ve ev sahibi yeniden başlatılana kadar bekletir. Model bu sırayı iki girdiyle kurar: işlemin adı ve ev sahibinin durumu.

```kotlin
// Main.kt — ev sahibinin durumuna gore fragment islemi
fun commit(op: String, hostState: String): Outcome =
    if (hostState == "stopped") Outcome.Waiting("ev-sahibi-baslatilmis") else Outcome.Given(op)

fun main() {
    val add = "add:ListFragment"
    val replace = "replace:DetailFragment"
    val asks = listOf(
        Ask("ekle-on-plan", add, commit(add, "resumed")),
        Ask("degistir-on-plan", replace, commit(replace, "resumed")),
        Ask("ekle-duran", add, commit(add, "stopped")),
        Ask("degistir-duran", replace, commit(replace, "stopped")),
    )
    for (ask in asks) {
        ask.report()
    }
    tally(asks)
}
```

```text
ekle-on-plan: istenen=add:ListFragment | verilen=add:ListFragment -> tam
degistir-on-plan: istenen=replace:DetailFragment | verilen=replace:DetailFragment -> tam
ekle-duran: istenen=add:ListFragment | bekledigi=ev-sahibi-baslatilmis -> bekleyen
degistir-duran: istenen=replace:DetailFragment | bekledigi=ev-sahibi-baslatilmis -> bekleyen
tam: 2
ikame: 0
bekleyen: 2
karsiliksiz: 0
```

Ön planda iki işlem de istendiği gibi uygulandı: tam. Ev sahibi durmuşken ikisi de bekledi, ve ikisinin de beklediği koşul aynıdır: `ev-sahibi-baslatilmis`. Beklemek reddetmek değildir; işlem kaybolmaz, ev sahibi yeniden başlatıldığında uygulanır. Dersin karşılaması bu yüzden **bekleyen**dir: fragment işleminin tipik sonucu, koşulunu adıyla taşıyan bir beklemedir.

**UB1.** Model ev sahibi durumunu iki değere indirir. Gerçek platform `created`, `started` ve `resumed` arasında işlem kuyruğunu ayrı ayrı yönetir; bu ayrım ölçülmedi.

## Geri Yığını ve Geri Düğmesi

`replace` kapsayıcıdaki eski fragment'ı atar. Geri yığınına eklenmemiş bir `replace` işleminde geri düğmesi eski fragment'a dönmez: activity'nin kendisinden çıkar. Kullanıcının beklediği, bir önceki ekrandır.

```kotlin
// Main.kt — geri yigini ile geri dugmesi
fun goBack(previous: String, addedToBackStack: Boolean): Outcome =
    if (addedToBackStack) Outcome.Given(previous) else Outcome.Given("activity-cikisi")

fun main() {
    val asks = listOf(
        Ask("yigitli-geri", "ListFragment", goBack("ListFragment", addedToBackStack = true)),
        Ask("yigitsiz-geri", "ListFragment", goBack("ListFragment", addedToBackStack = false)),
    )
    for (ask in asks) {
        ask.report()
    }
    tally(asks)
}
```

```text
yigitli-geri: istenen=ListFragment | verilen=ListFragment -> tam
yigitsiz-geri: istenen=ListFragment | verilen=activity-cikisi -> ikame
tam: 1
ikame: 1
bekleyen: 0
karsiliksiz: 0
```

Geri yığınına eklenen işlem `ListFragment`'ı geri getirdi: tam. Eklenmeyen işlemde de bir değer geldi, ama istenen değil: `activity-cikisi`. Geri düğmesi bir şey yaptı, kullanıcının istediğini yapmadı; bu ikamedir. Geri yığınının ayrıntısı, activity'ler arası geri yığınıyla birlikte, bu kursun son dersinde yeniden ele alınır.

**UB2.** Model tek bir önceki fragment'ı tutar. Gerçek geri yığını bir liste taşır ve kaç işlemin birden geri alınacağı `popBackStack` çağrısına bağlıdır.

## Fragment ve Görünümünün Ayrı Ömürleri

Bir fragment'ın iki ömrü vardır ve bunlar aynı anda bitmez. Fragment'ın kendisi, yani nesne, geri yığınında beklerken yaşamaya devam eder. Fragment'ın görünümü ise geri yığınına alındığı anda `onDestroyView` ile yok edilir ve kullanıcı geri dönünce `onCreateView` ile yeniden kurulur. Bu yüzden görünüme tuttuğunuz her referans, fragment geri yığınındayken bayatlar: nesne vardır, ama gösterdiği görünüm artık yoktur.

Bu fark, fragment'ta arayüze erişen kodun hangi geri çağrılar arasında güvenli olduğunu belirler. Görünüme erişim `onCreateView` ile `onDestroyView` arasındadır. Fragment'a bağlı bir gözlemci, görünümün ömrüne bağlanmalıdır.

```kotlin
// Platform kodu: gozlemciyi fragment degil gorunum omruna baglar
import androidx.lifecycle.Observer

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    viewModel.items.observe(viewLifecycleOwner, Observer { items ->
        showItems(items)
    })
}
```

Ölçümde istenen her zaman "arayüzü güncelle"dir. Fragment henüz görünüm kurmamışsa istek `onCreateView`i bekler. Görünüm kuruluysa tam karşılanır. Geri yığınında beklerken görünüm yoktur; istek karşılıksız kalır ve neden `gorunum-yok` olur.

```kotlin
// Main.kt — fragment gorunumunun omru
fun updateView(stage: String): Outcome = when (stage) {
    "eklendi" -> Outcome.Waiting("onCreateView")
    "gorunum-kurulu" -> Outcome.Given("guncellendi")
    "geri-yiginda" -> Outcome.Refused("gorunum-yok")
    else -> Outcome.Refused("fragment-yok")
}

fun main() {
    val asks = listOf("eklendi", "gorunum-kurulu", "geri-yiginda", "cikarildi").map {
        Ask("asama-$it", "guncellendi", updateView(it))
    }
    for (ask in asks) {
        ask.report()
    }
    tally(asks)
}
```

```text
asama-eklendi: istenen=guncellendi | bekledigi=onCreateView -> bekleyen
asama-gorunum-kurulu: istenen=guncellendi | verilen=guncellendi -> tam
asama-geri-yiginda: istenen=guncellendi | neden=gorunum-yok -> karsiliksiz
asama-cikarildi: istenen=guncellendi | neden=fragment-yok -> karsiliksiz
tam: 1
ikame: 0
bekleyen: 1
karsiliksiz: 2
```

İki karşılıksız satır aynı sonuca farklı yollardan varır. `fragment-yok`ta nesne de yoktur; kodun elinde bir referans bile olmaması beklenir. `gorunum-yok`ta ise nesne yaşar ve referans geçerli görünür, ama gösterdiği görünüm yoktur. İkincisi daha tehlikelidir, çünkü hata ancak çalışma anında ortaya çıkar. Çözüm, görünüm referansını `onDestroyView` içinde sıfırlamak ve gözlemcileri görünümün yaşam döngüsü sahibine bağlamaktır.

**UB3.** Model dört aşamayı ad olarak ayırır. Aşamalar arasındaki geçişlerin sırası, `onViewStateRestored` gibi ara geri çağrılar ve görünüm referansının nasıl sıfırlandığı ölçülmedi.

## Argümanlar ve Yeniden Oluşturma

Platform bir fragment'ı yeniden oluşturabilir: yapılandırma değişikliğinde ve süreç sonlanmasından sonra. Yeniden oluştururken fragment'ın yapıcısına parametre vermez. Varsayılan fabrika parametresiz yapıcıyı çağırır ve ardından fragment'a, oluşturulurken verilmiş olan `arguments` paketini bağlar. Yapıcı parametresi olarak verilen bir değer bu paketin içinde değilse, yeniden oluşturmada kaybolur.

```kotlin
// Platform kodu: degeri yapici yerine arguments paketiyle tasir
class ListFragment : Fragment() {
    companion object {
        fun newInstance(category: String) = ListFragment().apply {
            arguments = bundleOf("category" to category)
        }
    }
}
```

Ölçümde istenen kategori `kitap`tır. Değer üç ayrı yolla fragment'a verilmiştir: paketle, yapıcı parametresiyle ve parametresiz yapıcısı olmayan bir sınıf üzerinden.

```kotlin
// Main.kt — fragment yeniden olusturulurken degerin yolu
fun recreate(way: String): Outcome = when (way) {
    "arguments" -> Outcome.Given("kitap")
    "yapici-parametresi" -> Outcome.Given("tum")
    else -> Outcome.Refused("bos-yapici-yok")
}

fun main() {
    val asks = listOf("arguments", "yapici-parametresi", "yapici-yalniz-parametreli").map {
        Ask("yol-$it", "kitap", recreate(it))
    }
    for (ask in asks) {
        ask.report()
    }
    tally(asks)
}
```

```text
yol-arguments: istenen=kitap | verilen=kitap -> tam
yol-yapici-parametresi: istenen=kitap | verilen=tum -> ikame
yol-yapici-yalniz-parametreli: istenen=kitap | neden=bos-yapici-yok -> karsiliksiz
tam: 1
ikame: 1
bekleyen: 0
karsiliksiz: 1
```

Paketle verilen değer yeniden oluşturmadan sağ çıktı: tam. Yapıcı parametresiyle verilen değer ilk oluşturmada çalışır, ama yeniden oluşturmada varsayılana düşer; `tum` bir değerdir, istenen değil: ikame. Üçüncü yolda yeniden oluşturma hiç başlamaz, çünkü platform parametresiz bir yapıcı bulamaz. İkame burada en sinsi sonuçtur: uygulama çökmez, yalnız yanlış kategoriyi gösterir.

**UB4.** Model değerin kaybını varsayılana düşme olarak sabitler. Gerçek davranış yapıcının içinde değere ne yapıldığına bağlıdır, ve özel bir fragment fabrikası kullanıldığında parametreli yapıcı da çalışabilir; bu ölçülmedi.

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

Ev sahibi durmuşken işlem bekledi. Peki ev sahibi durumunu çoktan kaydetmişse? `onSaveInstanceState` çağrıldıktan sonra platform durumu paketlenmiş sayar; paketlenmiş durumun üstüne yeni bir işlem eklemek, süreç sonlanıp activity yeniden kurulduğunda işlemin kayıp olması demektir. Platform bu yüzden `commit`'i bu aşamada reddeder. `commitAllowingStateLoss` ise kaybı göze alarak işlemi uygular, ama işlemin durumu paketlenmez.

Aynı işlem bu yüzden üç farklı karşılama alabilir.

```kotlin
// Main.kt — ayni islem, durum kaydedildikten sonra uc karsilama
fun commitAfterSave(op: String, stateSaved: Boolean, allowLoss: Boolean): Outcome = when {
    !stateSaved -> Outcome.Given(op)
    allowLoss -> Outcome.Given("$op-durumsuz")
    else -> Outcome.Refused("durum-kaydedildi")
}

fun main() {
    val op = "add:ListFragment"
    val asks = listOf(
        Ask("kaydedilmemis", op, commitAfterSave(op, stateSaved = false, allowLoss = false)),
        Ask("kaydedilmis-commit", op, commitAfterSave(op, stateSaved = true, allowLoss = false)),
        Ask("kaydedilmis-kayipli", op, commitAfterSave(op, stateSaved = true, allowLoss = true)),
    )
    for (ask in asks) {
        ask.report()
    }
    tally(asks)
}
```

```text
kaydedilmemis: istenen=add:ListFragment | verilen=add:ListFragment -> tam
kaydedilmis-commit: istenen=add:ListFragment | neden=durum-kaydedildi -> karsiliksiz
kaydedilmis-kayipli: istenen=add:ListFragment | verilen=add:ListFragment-durumsuz -> ikame
tam: 1
ikame: 1
bekleyen: 0
karsiliksiz: 1
```

Durum kaydedilmemişken işlem tam uygulandı. Kaydedildikten sonra `commit` karşılıksız kaldı; neden `durum-kaydedildi`. `commitAllowingStateLoss` ise bir değer verdi, ama işlemin kendisi değil, durumsuz hali: ikame. Üç satır üç farklı karşılamadır ve işlem aynıdır.

Bu satırlar bekleyenle karşılıksız arasındaki sınırı da çizer. Ev sahibi durmuşken platform işlemin sonra uygulanabileceğini bilir ve bekletir. Durum kaydedildikten sonra işlemin bekleyeceği bir koşul yoktur: koşul geçmiştir, ve işlem artık güvenle uygulanamaz.

**UB5.** Model gerçek platformdaki istisnayı fırlatmaz; reddi `Refused` olarak döndürür. Platformda `commit` bu durumda bir istisnayla sona erer.

## Özet

- Bu dersin ölçütü: **karşılama**. Fragment işlemi, ev sahibi activity'nin durumuna göre karşılanır. Bu dersin karşılaması: **bekleyen**.
- Ev sahibi ön planda iken işlemler tam, durmuşken bekleyen karşılandı: 2 tam ve 2 bekleyen.
- Geri yığınına eklenmeyen işlemde geri düğmesi activity'den çıkar; istenen fragment yerine başka bir değer gelir: ikame.
- Durum kaydedildikten sonra `commit` karşılıksız, `commitAllowingStateLoss` ikame kalır; aynı işlem üç karşılama alır.
- Bekleyen, koşulu gelecekte sağlanabilen istektir; karşılıksız, koşulun geçtiği istektir.

## Sonraki Adım

Fragment'lar arayüz bölümleridir; arka planda çalışan işin arayüzü yoktur. Sıradaki ders, `Servisler`, arayüzsüz uygulama bileşenini ve platformun arka plandan başlatılan bir servise koyduğu kuralı ölçer.
