← Back to list

Flutter’da Debounce ve Throttle ile Akıllı Etkileşimler Yaratmak

Merhaba değerli okurlar. Bir arama çubuğu düşünün. Kullanıcı “Flutter” kelimesini yazmaya başlar. “F”… “Fl”… “Flu”… Her tuş vuruşunda…

AbdullahTaş · 2025-10-01 11:31 · 5 claps · 4.4 min read
#flutter #flutter-app-development #dart #debounce #throttle
Open on Medium ↗
Wiki topics: 📱 · Mobile Development

Flutter’da Debounce ve Throttle ile Akıllı Etkileşimler Yaratmak

Merhaba değerli okurlar. Bir arama çubuğu düşünün. Kullanıcı “Flutter” kelimesini yazmaya başlar. “F”… “Fl”… “Flu”… Her tuş vuruşunda, uygulamanız sunucuya koşarak bir API isteği gönderir. Kullanıcı daha kelimeyi bitiremeden, siz sunucuyu 7 anlamsız ve gereksiz istekle bombalamış olursunuz. Ya da bir butona tekrar tekrar basılmasına izin veren bir “beğen” butonu… Kullanıcı bir anlık sabırsızlıkla butona beş kez basar ve siz arka planda aynı işlemi beş kez tetiklersiniz.

Bu senaryolar, “Aşırı Ateşleme” (Over-firing) olarak bilinen yaygın bir problemdir ve acemice tasarlanmış bir uygulamanın en belirgin işaretlerindendir. Bu sadece sunucu kaynaklarını ve kullanıcının mobil verisini israf etmekle kalmaz, aynı zamanda uygulamanızın yavaş, tepkisiz ve hatta kararsız hissettirmesine neden olur.

Profesyonel bir Flutter uygulaması, kullanıcıdan gelen olayları (events) körü körüne işleme almaz. Onları bir filtreden geçirir, zamanlamasını ayarlar ve sadece “anlamlı” olanları işler. Bu akıllı filtreleme işlemini yapmak için kullandığımız iki temel ve güçlü teknik vardır: Debouncing ve Throttling.

Bu makalede, bu iki tekniğin ne olduğunu, aralarındaki ince ama kritik farkları ve Dart dilinde Timer gibi temel araçlarla veya rxdart gibi güçlü kütüphanelerle nasıl hayata geçirileceğini derinlemesine inceleyeceğiz.

Bu makalenin sonunda:

  • Bir arama çubuğunun sunucunuzu nasıl bir DDoS saldırısına maruz bırakabileceğini ve bunu nasıl önleyeceğinizi öğreneceksiniz.
  • Debouncing ve Throttling arasındaki farkı, basit ve akılda kalıcı metaforlarla anlayacaksınız.
  • Bu teknikleri, sıfırdan, kendi yardımcı sınıflarını (helper classes) yazarak nasıl uygulayacağını göreceksiniz.
  • Uygulamalarını daha verimli, daha akıllı ve hem sunucuya hem de kullanıcıya karşı daha iyi hale getireceksiniz.

Bu konuyla ilgili örnek uygulama reposunada buradan erişebilirsiniz; https://github.com/abdullah017/flutter-debounce-thorttle-example

Bölüm 1: İki Farklı Zamanlama Felsefesi

Debouncing ve Throttling, sık tetiklenen bir olayı kontrol altına almak için kullanılır, ancak bunu tamamen farklı felsefelerle yaparlar.

Debouncing (Sakinleşmesini Bekle)

Asansörün kapı kapatma düğmesini düşünün. Birisi butona bastığı sürece kapı açık kalır. Butona basma eylemi durduktan belirli bir süre sonra (örneğin 3 saniye) kapı kapanır. Eğer o 3 saniye içinde biri tekrar basarsa, zamanlayıcı sıfırlanır ve kapı 3 saniye daha bekler.

  • Bir olayın tetiklenmesini, olayların akışı durduktan belirli bir süre sonraya ertelemektir. Olaylar gelmeye devam ettiği sürece, asıl fonksiyon asla çalışmaz.

İdeal Kullanım Alanları:

  • Arama Çubuğu (TextField onChanged): Kullanıcı yazmayı bitirdikten sonra tek bir arama isteği göndermek.
  • Pencere Boyutlandırma: Kullanıcı pencereyi sürüklemeyi bıraktıktan sonra UI’ı yeniden hesaplamak.
  • Otomatik Kaydetme: Kullanıcı metin girmeyi durdurduktan bir süre sonra taslağı kaydetmek.

Throttling (Nefes Almasına İzin Ver)

Bir video oyununda özel bir yeteneği kullanmak gibi düşünebilirsiniz. Yeteneği kullandıktan sonra, tekrar kullanabilmek için bir “bekleme süresi” (cooldown) girer. O süre boyunca ne kadar tuşa basarsanız basın, yetenek çalışmaz. Süre dolduğunda ise sadece ilk basışınız geçerli olur.

  • Bir olayın, belirli bir zaman aralığı içinde en fazla bir kez tetiklenmesini sağlamaktır. Olaylar ne kadar sık gelirse gelsin, fonksiyon belirlenen aralıktan daha sık çalışamaz.

İdeal Kullanım Alanları:

  • Kaydırma Pozisyonunu Dinleme (ScrollController): Kullanıcı listeyi kaydırırken, pozisyonu saniyede 60 kez değil, her 200 milisaniyede bir kontrol etmek.
  • Butona Tekrar Basmayı Önleme: Bir “Gönder” veya “Beğen” butonuna basıldıktan sonra, bir saniye boyunca tekrar basılmasını engellemek.
  • Sürükleme (Drag) Olayları: Bir nesneyi sürüklerken pozisyonunu sürekli değil, belirli aralıklarla güncellemek.

Özetle Debounce bir olay serisinin sonunu beklerken, Throttle bu seriyi düzenli aralıklarla seyreltir.

Bölüm 2: Pratik Uygulama

Bu konseptleri anlamanın en iyi yolu, onları kendimiz yazmaktır. dart:async kütüphanesindeki Timer’ı kullanarak basit ama güçlü yardımcı sınıflar oluşturalım.

Debouncer Sınıfı

lib/utils/debouncer.dart:

import 'dart:async';
import 'package:flutter/foundation.dart';

class Debouncer {
  final int milliseconds;
  Timer? _timer;

  Debouncer({required this.milliseconds});

  // 'action' parametresi, geciktirilerek çalıştırılacak olan asıl fonksiyondur.
  void run(VoidCallback action) {
    // Eğer önceki bir timer varsa, onu iptal et.
    // Bu, "asansör düğmesine tekrar basılması" senaryosudur.
    if (_timer?.isActive ?? false) {
      _timer!.cancel();
    }

    // Yeni bir timer başlat. Belirtilen süre dolduğunda 'action' çalışacak.
    _timer = Timer(Duration(milliseconds: milliseconds), action);
  }

  // Widget dispose olduğunda timer'ı temizlemek için.
  void dispose() {
    _timer?.cancel();
  }
}

Kullanımı (Arama Çubuğu Senaryosu):

lib/presentation/search_page.dart:

class _SearchPageState extends State<SearchPage> {
  // 500ms bekleme süreli bir Debouncer oluştur.
  final _debouncer = Debouncer(milliseconds: 500);

  void _search(String query) {
    // Bu metot, her tuş vuruşunda çağrılmayacak.
    // Sadece kullanıcı yazmayı bıraktıktan 500ms sonra çağrılacak.
    print('Searching for: $query');
    // ... API isteğini burada yap ...
  }

  @override
  Widget build(BuildContext context) {
    return TextField(
      onChanged: (value) {
        // Her tuş vuruşunda 'run' metodunu çağırıyoruz.
        // Debouncer, _search fonksiyonunu ne zaman çalıştıracağına karar verecek.
        _debouncer.run(() => _search(value));
      },
    );
  }

  @override
  void dispose() {
    _debouncer.dispose(); // Temizlik yapmayı unutma!
    super.dispose();
  }
}

Bu basit yapı sayesinde, kullanıcı “Flutter is amazing” yazarken 19 API isteği yerine, yazmayı bitirdikten sonra sadece bir tane istek gönderilir!

Throttler Sınıfı (Basit Bir Versiyon)

lib/utils/throttler.dart:

import 'dart:async';
import 'package:flutter/foundation.dart';

class Throttler {
  final int milliseconds;
  Timer? _timer;
  bool _isReady = true;

  Throttler({required this.milliseconds});

  void run(VoidCallback action) {
    // Eğer "bekleme süresi" (cooldown) aktif değilse, fonksiyonu çalıştır.
    if (_isReady) {
      action();
      // Durumu 'beklemede' yap ve bir timer başlat.
      _isReady = false;
      _timer = Timer(Duration(milliseconds: milliseconds), () {
        // Süre dolduğunda durumu tekrar 'hazır' yap.
        _isReady = true;
      });
    }
    // Eğer bekleme süresi aktifse, hiçbir şey yapma.
  }

  void dispose() {
    _timer?.cancel();
  }
}

Kullanımı (Butona Tekrar Basmayı Önleme):

class _MyButtonState extends State<MyButton> {
  // 2 saniyelik bir bekleme süresi olan Throttler oluştur.
  final _throttler = Throttler(milliseconds: 2000);

  void _submit() {
    print('Form submitted!');
    // ... API isteği veya veritabanı işlemi ...
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        // Throttler, _submit fonksiyonunun 2 saniyede bir defadan fazla
        // çağrılmamasını garanti edecek.
        _throttler.run(() => _submit());
      },
      child: Text('Submit'),
    );
  }

  @override
  void dispose() {
    _throttler.dispose();
    super.dispose();
  }
}

Artık kullanıcı butona ne kadar hızlı basarsa bassın, _submit fonksiyonu sadece ilk basışta çalışacak ve 2 saniye boyunca tekrar çalışmayacaktır.

Bölüm 3: rxdart ile Reaktif Yaklaşım

Sıfırdan yazmak öğretici olsa da, daha karmaşık senaryolar ve reaktif programlama için rxdart kütüphanesi, debounceTime ve throttleTime gibi hazır ve güçlü operatörler sunar.

rxdart ile Debounce:

// StreamController, olayların akışını yönetir.
final _searchController = StreamController<String>();

_searchController.stream
  // Gelen olayları 500ms geciktirir.
  .debounceTime(const Duration(milliseconds: 500))
  // Sadece birbirinden farklı olan olayları geçirir.
  .distinct()
  // Son olarak, asıl arama fonksiyonunu çağırır.
  .listen((query) {
    _search(query);
  });

// TextField'ın onChanged'inde:
onChanged: (value) => _searchController.add(value),

Bu yaklaşım, kodunuzu daha deklaratif ve okunabilir hale getirir. Özellikle birden fazla olayı birleştirmeniz veya dönüştürmeniz gereken karmaşık senaryolarda rxdart paha biçilmezdir.

Debouncing ve Throttling, bir geliştiricinin araç çantasındaki en keskin bıçaklardan ikisidir. Onlar, uygulamalarımızı sadece daha performanslı kılmakla kalmaz, aynı zamanda daha düşünceli ve akıllı hale getirir.

  • Debounce ile kullanıcıya “Seni anlıyorum, bitirmeni bekliyorum” deriz.
  • Throttle ile sisteme “Sakin ol, her şeyi aynı anda yapmana gerek yok” deriz.

Bu teknikleri öğrendiğinizde, kullanıcı etkileşimlerine artık basit bir “tetikleyici” olarak bakmayacaksınız. Onları, uygulamanızın kaynaklarını ve kullanıcının deneyimini en verimli şekilde yönetmek için kontrol etmeniz gereken bir olay akışı olarak göreceksiniz.

Umarım bu makale ilgilisi ve meraklısı için faydalı olur. Sonraki yazılarda görüşmek üzere.

Github: www.github.com/abdullah017 Linkedin: www.linkedin.com/in/abdullahtas Stackoverflow: https://stackoverflow.com/users/13807726/abdullah-t

#FREEPALESTINA


메타데이터
post_id
e42e844f7865
slug
flutterda-debounce-ve-throttle-ile-akıllı-etkileşimler-yaratmak-e42e844f7865
url
https://medium.com/@abdullahtas/flutterda-debounce-ve-throttle-ile-ak%C4%B1ll%C4%B1-etkile%C5%9Fimler-yaratmak-e42e844f7865
canonical_url
https://medium.com/@abdullahtas/flutterda-debounce-ve-throttle-ile-ak%C4%B1ll%C4%B1-etkile%C5%9Fimler-yaratmak-e42e844f7865
author_url
https://medium.com/@abdullahtas
status
ok
fetched_at
2026-07-15 01:38:33