---
title: 'Geliştirici Araçları'
source: 'https://academia.sh/tr/kurslar/flutter/gelistirici-araclari'
course: Flutter
language: tr
updated: '2026-10-21T05:02:53+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Bileşen inceleyicisinin, düzen incelemenin ve başarım görünümünün neyi gösterdiğini ayırır'
    - 'İnceleyicideki kısıt ve genişlik değerlerini ölçülen kayıtla eşler'
    - 'Beklenmedik geniş görünen bir bileşenin nedenini kısıttan okur'
    - 'Sıcak yeniden yüklemenin ağacı yeniden kurduğunu, durumu korumasını açıklar'
---

# Geliştirici Araçları

Bileşen inceleyicisi, düzen inceleme ve başarım görünümü bir ağacı çalışırken gösterir. Ders inceleyicinin gösterdiği kısıt ve genişliği ölçülen kayıtla eşler.

Önceki derste bir test kaldı ve hatanın hangi yolda olduğu söylendi. Neden böyle olduğunu görmek ise başka bir işin konusu: ağacı çalışırken açıp bakmak. Bu ders, çerçevenin geliştirme araçlarını boyutlanma ekseniyle okur. Bir araç ekranda bir bileşenin genişliğini gösterdiğinde, aslında kursun sorusunu cevaplıyor: bu genişliği kim belirledi.

## Dört Araç

**Bileşen inceleyicisi** çalışan uygulamanın bileşen ağacını gösterir. Bir bileşen seçildiğinde yalnız onun özelliklerini değil, aldığı kısıtı ve ortaya çıkan boyutu da görürsünüz. Çerçevenin belgesi bu konuda şunu söyler: "The constraints flow down the tree, and the sizes flow back up." Yani kısıtlar ağaçta aşağı iner, boyutlar yukarı çıkar; düzen sorunlarında bakılacak iki alan `size` ve `constraints` alanlarıdır.

**Düzen inceleme**, inceleyicinin içinde esnek bileşenler için ayrı bir görünümdür. Satır, sütun ya da esnek çocuklarla ilgili bir bileşen seçildiğinde esnek çarpanı, esnek uyumu ve kısıtlar görselleştirilir; kısıt ihlalleri kırmızıyla, taşma hataları sarı şeritli bir desenle gösterilir. Bu görünümde değiştirdiğiniz değerler kaynak koda yazılmaz ve sıcak yeniden yüklemede geri alınır.

**Başarım görünümü** genişlik değil zaman gösterir: kareleri bir çizelgede dizer, yavaş kalan kareleri kırmızı işaretler ve bir karede hangi işin yapıldığını olay çizelgesinde açar. Bileşen yapılarının hangi anda kurulduğunu gösteren bir seçenek de vardır. Belge, ölçümün geliştirme kipinde değil başarım ölçüm kipinde alınmasını önerir, çünkü geliştirme kipindeki kare süreleri yayın sürümünün başarımını yansıtmaz. Bu dersin sayıları süre içermez; başarım görünümü bir sonraki dersin konusudur.

**Sıcak yeniden yükleme** değişen kaynak kodu çalışan uygulamaya yollar ve ağacı yeniden kurar. `main` ve `initState` yeniden çalışmaz; uygulamanın durumu korunur. Belgeye göre bu yalnız geliştirme kipinde çalışır. Durum korunduğu için kaynak koddaki bir değişiklik ekranda görünmeyebilir: örneğin başlangıç değerini değiştirmek, değer zaten kurulmuşsa bir etki yaratmaz. O zaman uygulamayı baştan başlatan sıcak yeniden başlatma gerekir.

## Ölçülen Katman

Kursun her dersi aynı düz Dart modelini kullanır. Model bir bileşen ağacına ekran genişliğini verir ve her düğümün genişliğini kimin belirlediğini dört adla kaydeder. Aşağıdaki dosya çıktı üretmez; ölçülen bloklar onu içe alır.

```dart
// sizing.dart — bir bilesenin genisligini kimin belirledigini siniflandirir
const sizings = ['dayatilan', 'secilen', 'kirpilan', 'esnetilen'];

class Limit {
  final int min;
  final int? max; // null: sinirsiz
  const Limit(this.min, this.max);

  bool get tight => max == min;
  Limit loosen() => Limit(0, max);
  Limit deflate(int by) => Limit(_floor(min - by), max == null ? null : _floor(max! - by));
  String bounds() => '$min..${max ?? 'sonsuz'}';
}

int _floor(int value) => value < 0 ? 0 : value;

class Part {
  final String kind;
  final String name;
  final int? width; // null: alabildigi kadar genis
  final List<Part> children;
  final int factor;
  final bool tightFlex;
  const Part(this.kind, this.name, this.width, this.children,
      {this.factor = 0, this.tightFlex = true});
}

Part leaf(String name, int width) => Part('leaf', name, width, const []);
Part fill(String name) => Part('leaf', name, null, const []);
Part pad(String name, int padding, Part child) => Part('pad', name, padding, [child]);
Part center(String name, Part child) => Part('center', name, null, [child]);
Part fixed(String name, int width, Part child) => Part('fixed', name, width, [child]);
Part column(String name, List<Part> children) => Part('column', name, null, children);
Part row(String name, List<Part> children) => Part('row', name, null, children);
Part flex(String name, int factor, Part child, {bool tight = true}) =>
    Part('flex', name, null, [child], factor: factor, tightFlex: tight);

class Sizing {
  final String sizing;
  final String path;
  final int width;
  final Limit limit;
  const Sizing(this.sizing, this.path, this.width, this.limit);
}

Sizing classify(String path, int? desire, Limit limit) {
  if (limit.tight) return Sizing('dayatilan', path, limit.min, limit);
  if (desire == null) {
    return limit.max == null
        ? Sizing('kirpilan', path, limit.min, limit)
        : Sizing('esnetilen', path, limit.max!, limit);
  }
  if (desire < limit.min) return Sizing('kirpilan', path, limit.min, limit);
  if (limit.max != null && desire > limit.max!) {
    return Sizing('kirpilan', path, limit.max!, limit);
  }
  return Sizing('secilen', path, desire, limit);
}

int layout(Part part, Limit limit, List<Sizing> log, [String path = '']) {
  final here = '$path/${part.name}';
  final below = <Sizing>[];
  if (part.kind == 'fixed') {
    final own = classify(here, part.width, limit);
    layout(part.children.first, Limit(own.width, own.width), below, here);
    log..add(own)..addAll(below);
    return own.width;
  }
  int? desire;
  switch (part.kind) {
    case 'leaf':
      desire = part.width;
    case 'pad':
      final space = 2 * part.width!;
      desire = layout(part.children.first, limit.deflate(space), below, here) + space;
    case 'center':
      final inner = layout(part.children.first, limit.loosen(), below, here);
      desire = limit.max == null ? inner : null;
    case 'flex':
      desire = layout(part.children.first, limit, below, here);
    case 'column':
      var widest = 0;
      for (final child in part.children) {
        final width = layout(child, limit.loosen(), below, here);
        if (width > widest) widest = width;
      }
      desire = widest;
    case 'row':
      final logs = [for (final _ in part.children) <Sizing>[]];
      final bounded = limit.max != null;
      var used = 0;
      var factors = 0;
      for (var i = 0; i < part.children.length; i++) {
        final child = part.children[i];
        if (child.kind == 'flex' && bounded) {
          factors += child.factor;
        } else {
          used += layout(child, const Limit(0, null), logs[i], here);
        }
      }
      final left = bounded ? _floor(limit.max! - used) : 0;
      var given = 0;
      var seen = 0;
      for (var i = 0; i < part.children.length; i++) {
        final child = part.children[i];
        if (child.kind != 'flex' || !bounded) continue;
        seen += child.factor;
        final share = (seen == factors ? left : left * seen ~/ factors) - given;
        given += share;
        final room = child.tightFlex ? Limit(share, share) : Limit(0, share);
        used += layout(child, room, logs[i], here);
      }
      for (final entries in logs) {
        below.addAll(entries);
      }
      desire = bounded ? null : used;
  }
  final own = classify(here, desire, limit);
  log..add(own)..addAll(below);
  return own.width;
}

List<Sizing> measure(Part root, int screen) {
  final log = <Sizing>[];
  layout(root, Limit(screen, screen), log);
  return log;
}

void printSizes(List<Sizing> log) {
  for (final entry in log) {
    print('${entry.sizing}: ${entry.path} genislik=${entry.width} kisit=${entry.limit.bounds()}');
  }
}

void countSizings(List<Sizing> log) {
  for (final name in sizings) {
    print('$name: ${log.where((entry) => entry.sizing == name).length}');
  }
  print('ebeveyn: ${log.where((entry) => entry.sizing != 'secilen').length}');
}
```

Bu derste model, bu boyutlanmanın kuralını kurar; model çerçevenin kendisi değildir. Modelde inceleyicinin bir bileşen için gösterdiği iki değer, `printSizes` çıktısındaki `genislik` ve `kisit` alanlarıdır. Model başarım görünümünü ya da sıcak yeniden yüklemeyi taşımaz; ikincisine ağacı yeniden ölçerek yaklaşılır.

## İncelenen Ekran

Ekranın ağacı bir sütundur: 150 birim isteyen bir etiket ve bir `Center` içinde 80 birim isteyen bir `Chip`. Ağaç, çipin genişliğini alan bir işlevle kurulur.

```dart
// panel_model.dart — incelenen ekranin bilesen agaci
import 'sizing.dart';

Part buildPanel(int chipWidth) => pad('Screen', 16, column('Body', [
      leaf('Label', 150),
      center('Center', leaf('Chip', chipWidth)),
    ]));
```

Bu ağacın kaynak karşılığında `Center` yalnız çipi sarmalar. Geliştirici çipin 80 birim olduğunu bilir ve ona ayrılan alanın da yaklaşık o kadar olmasını bekler. Bu beklenti, inceleyiciye bakılana kadar sürer.

## Beklenmedik Geniş Görünen Bileşen

Ekran 360 birim genişliğinde. Aşağıdaki blok kaydın tamamını basar; her satır, inceleyicinin bir bileşen için göstereceği değerlerdir.

```dart
// main.dart
import 'sizing.dart';
import 'panel_model.dart';

void main() {
  final log = measure(buildPanel(80), 360);
  printSizes(log);
}
```

```text
dayatilan: /Screen genislik=360 kisit=360..360
dayatilan: /Screen/Body genislik=328 kisit=328..328
secilen: /Screen/Body/Label genislik=150 kisit=0..328
esnetilen: /Screen/Body/Center genislik=328 kisit=0..328
secilen: /Screen/Body/Center/Chip genislik=80 kisit=0..328
```

`Chip` 80 birim ister ve 80 birim alır: seçilen. `Center` ise 328 birimdir, çipten çok daha geniş. Sınırlı bir kısıtta ortalayan bileşen isteğini bildirmez; kendisine verilen en geniş değere yayılır. Kursun dilinde bu, esnetilen boyutlanmadır. İnceleyicide `Center` seçildiğinde göreceğiniz `size` 328, `constraints` ise 0 ile 328 arasıdır. Geliştirici çipe bakıp `Center`'ın da dar olmasını bekliyordu; oysa genişliği çip değil, ebeveynin kısıtı belirledi.

## Kısıt Kardeşe de Aynen İner

M11/K05'te bir işlemin kaynağa ne bıraktığı sorulurdu: kaynak bir kez tüketildi mi, ardından hâli nedir. Düzen kısıtı için bu soru geçersizdir, çünkü düzen kısıtı tüketilmez. Sütun gövdeye gelen kısıtı gevşetir ve her çocuğa aynı gevşek kısıtı verir; etiket aldığında `Center`'ın payı eksilmez. Aşağıdaki blok, `0..328` kısıtını alan tüm bileşenleri listeler.

```dart
// main.dart
import 'sizing.dart';
import 'panel_model.dart';

void main() {
  final log = measure(buildPanel(80), 360);
  printSizes(log.where((entry) => entry.limit.bounds() == '0..328').toList());
}
```

```text
secilen: /Screen/Body/Label genislik=150 kisit=0..328
esnetilen: /Screen/Body/Center genislik=328 kisit=0..328
secilen: /Screen/Body/Center/Chip genislik=80 kisit=0..328
```

`Label` ve `Center` aynı kısıtı alır. `Chip` de aynı kısıtı alır, çünkü ortalayan bileşen kısıtı gevşetir ama üst sınırı korur. İnceleyicide yan yana duran iki kardeşin kısıt alanı bu yüzden aynı görünür. Kısıtı daraltan tek şey iç boşluktur ve o ağaçta yalnız `Screen` düzeyindedir.

## Taşma ve Düzen İnceleme

Çipin isteği kısıtı aşarsa ne olur? Aşağıdaki blok çipi 400 birim yapar ve `Center` altındaki kayıtlara bakar.

```dart
// main.dart
import 'sizing.dart';
import 'panel_model.dart';

void main() {
  final log = measure(buildPanel(400), 360);
  printSizes(log.where((entry) => entry.path.startsWith('/Screen/Body/Center')).toList());
}
```

```text
esnetilen: /Screen/Body/Center genislik=328 kisit=0..328
kirpilan: /Screen/Body/Center/Chip genislik=328 kisit=0..328
```

Çip 400 ister, izin verilen en çok 328'dir. Genişliği 328'e çekilir ve kırpılan olur. Gerçek çerçevede aynı durum bir taşma hatası olarak görünür: düzen incelemenin sarı şeritli deseni tam burada işe yarar. Modelde taşma bir görüntü değil, bir sınıftır; kayıt yalnız isteğin aralık dışında kaldığını söyler.

## Sıcak Yeniden Yükleme Ağacı Yeniden Ölçer

Sıcak yeniden yükleme ağacı yeniden kurar. Modelde bunun karşılığı, yeni durumla aynı ağaç işlevini çağırıp ağacı yeniden ölçmektir. Aşağıdaki blok çip genişliğini 80'den 400'e çevirir ve iki ölçümün sayımını yan yana basar.

```dart
// main.dart
import 'sizing.dart';
import 'panel_model.dart';

void main() {
  for (final chip in [80, 400]) {
    print('chip=$chip');
    countSizings(measure(buildPanel(chip), 360));
  }
}
```

```text
chip=80
dayatilan: 2
secilen: 2
kirpilan: 0
esnetilen: 1
ebeveyn: 3
chip=400
dayatilan: 2
secilen: 1
kirpilan: 1
esnetilen: 1
ebeveyn: 4
```

Çip değeri değişince bir bileşen seçilenden kırpılana geçer; ebeveyn sayısı üçten dörde çıkar. Gerçek sıcak yeniden yüklemede uygulamanın durumu korunur; modelde ise yeniden ölçme her seferinde sıfırdan bir ağaç kurar. Modelin korunan durumu yoktur.

## Aracın Gösterdiğini Okumak

Bir inceleyiciye bakarken izlenecek sıra basittir. Önce bileşeni seç. Sonra aldığı kısıta bak: sıkıysa boyutu ebeveyn dayatmıştır. Sınırlı ve gevşekse bileşenin kendi isteğine bak: istek aralığa sığıyorsa seçilen, sığmıyorsa kırpılan. İstek yoksa ve üst sınır sonluysa genişlik üst sınırdır: esnetilen. Bu üç soru dört boyutlanmanın hepsini ayırır.

Aşağıdaki iki parça, aynı sorunun çerçeve kodundaki karşılığıdır. İlki ekranda her bileşenin sınırlarını çizen bir bayrağı açar; ikincisi ortalanmış bir sarmalayıcıyı gösterir.

```dart
// Platform kodu: duzen sinirlarini cizmek
void main() {
  debugPaintSizeEnabled = true;
  runApp(const ExampleScreen());
}
```

Bu bayrak her bileşenin sınırını çizer ve yalnız geliştirme kipinde etkilidir.

```dart
// Platform kodu: ortalanmis sarmalayici
Column(
  children: [
    const Text('Etiket'),
    Center(child: Chip(label: Text('Etiket'))),
  ],
)
```

Bu iki satırlık düzende `Center` kendisine verilen genişliğe yayılır. İnceleyici bu yayılmayı gösterir; modelde de aynı yayılma `Center` düğümü için ölçülmüştür.

## Yaygın Yanılgı

**İnceleyicide geniş görünen bileşenin içeriği de geniştir.** Böyle değildir. `Center` 328 birimdir ama içindeki çip 80 birimdir. Bileşenin sınırı ile içeriği ayrı şeylerdir; inceleyici sınırı gösterir, içeriğin kendi isteğini ayrıca okumak gerekir.

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

Son ölçüm, kuralın inceleyici gibi yalnız o anki kısıtı gördüğünü gösterir. Ekran 360 birimden 240 birime inince `Center`'ın genişliği çipe değil ekrana bağlı kalır.

```dart
// main.dart
import 'sizing.dart';
import 'panel_model.dart';

void main() {
  for (final screen in [360, 240]) {
    final log = measure(buildPanel(80), screen);
    printSizes(log.where((entry) => entry.path == '/Screen/Body/Center').toList());
  }
}
```

```text
esnetilen: /Screen/Body/Center genislik=328 kisit=0..328
esnetilen: /Screen/Body/Center genislik=208 kisit=0..208
```

Odak düğüm `/Screen/Body/Center`. İki ekranda da esnetilen çıkar; genişliği 328'den 208'e iner, çip ise iki ölçümde de 80 birimdir. Dersin boyutlanması bu yüzden esnetilendir: ortalayan bileşenin genişliğini ekran belirler.

**KY1.** Model, bu boyutlanmanın kuralını kurar; model çerçevenin kendisi değildir. Modelde inceleyicinin değeri bir kayıt satırıdır. Gerçek inceleyici bir bileşenin yalnız kısıt ve boyutunu değil, çizim nesnesinin özelliklerini ve esnek çarpanını da gösterir; bunlar modelde yoktur. Başarım görünümünün kare çizelgesi ve sıcak yeniden yüklemenin korunan durumu da modelde ölçülmez.

## Özet

- Bu dersin boyutlanması: esnetilen. `Center` sınırlı kısıtta isteğini bildirmedi ve 328 birime yayıldı; içindeki çip 80 birimde seçilen kaldı.
- Bileşen inceleyicisi kısıt ve boyutu, düzen inceleme esnek bileşenleri, başarım görünümü kareleri gösterir.
- İnceleyicinin gösterdiği kısıt ve genişlik, modelde `printSizes` satırının `kisit` ve `genislik` alanlarıdır.
- Düzen kısıtı tüketilmez: aynı gevşek kısıt `Label`, `Center` ve `Chip` için de `0..328` olarak indi.
- Sıcak yeniden yükleme ağacı yeniden kurar ve durumu korur; modelde karşılığı ağacı yeni durumla yeniden ölçmektir.

## Sonraki Adım

İnceleyici bir sorunu gösterir, ama çoğu zaman sorun yanlış genişlik değil gereksiz iştir. Sıradaki ders, `Başarım Ayarı`, ağaçta gereksiz yeniden kurmayı azaltan yöntemleri ve bir bileşenin değişikliğinin yukarıya sızmadığı yeniden düzen sınırını ele alır.
