Flutter İle Liste Görünümünde Arama Filtreleme Nasıl Yapılır?

Flutter İle Liste Görünümünde Arama Filtreleme Nasıl Yapılır?
Flutter İle Liste Görünümünde Arama Filtreleme Nasıl Yapılır?

Ön Hazırlık ve Gereksinimler

Uygulamaya başlamadan önce geliştirme ortamınızın güncel olduğundan emin olmalısınız. 2026 standartlarında Flutter 3.x veya üzeri bir sürüm kullanmanız, performans iyileştirmelerinden yararlanmanız için önemlidir.

  • Flutter SDK (En güncel kararlı sürüm).
  • Dart programlama dili temel bilgisi.
  • Bir kod editörü (VS Code veya Android Studio).
  • Temel "StatefulWidget" mantığına hakimiyet.

Projenizde herhangi bir dış paket kullanmadan, Flutter'ın sunduğu yerel TextEditingController ve setState mekanizmalarıyla bu işlemi gerçekleştireceğiz. Bu yaklaşım, gereksiz bağımlılıkları azaltarak uygulamanızın boyutunu optimize etmenizi sağlar.

Adım 1: Veri Modeli ve Liste Hazırlığı

Filtreleme işlemi yapabilmek için öncelikle üzerinde işlem yapacağımız bir veri setine ihtiyacımız var. Bir kullanıcı listesi oluşturarak işe başlayalım. Veri modeli, filtreleme mantığının temelini oluşturur.


class Kullanici {
  final String isim;
  final String email;

  Kullanici({required this.isim, required this.email});
}

final List tumKullanicilar = [
  Kullanici(isim: "Ahmet Yılmaz", email: "ahmet@example.com"),
  Kullanici(isim: "Ayşe Demir", email: "ayse@example.com"),
  Kullanici(isim: "Mehmet Kaya", email: "mehmet@example.com"),
];

Yukarıdaki kod bloğunda, basit bir Kullanici sınıfı tanımladık ve örnek verilerle bir liste oluşturduk. Bu liste, filtreleme işlemi sırasında referans alacağımız ana veri kaynağı (source of truth) olacaktır.

Adım 2: Arama Filtreleme İçin Gerekli Değişkenleri Tanımlama

Filtreleme mantığı için iki farklı listeye ihtiyacımız vardır: Biri tüm veriyi tutan ana liste, diğeri ise ekranda gösterilecek olan filtrelenmiş liste. Ayrıca kullanıcının yazdığı metni takip etmek için bir TextEditingController tanımlamalıyız.


class AramaSayfasi extends StatefulWidget {
  @override
  _AramaSayfasiState createState() => _AramaSayfasiState();
}

class _AramaSayfasiState extends State {
  List gorunenListe = [];
  TextEditingController aramaController = TextEditingController();

  @override
  void initState() {
    super.initState();
    gorunenListe = tumKullanicilar; // Başlangıçta tüm listeyi göster
  }
}

initState metodu içerisinde gorunenListe değişkenini ana listeye eşitledik. Böylece uygulama ilk açıldığında tüm kullanıcılar ekranda listelenmiş olur.

Adım 3: Arama Mantığını (Filtreleme Fonksiyonu) Oluşturma

Filtreleme fonksiyonu, kullanıcının girdiği metni alır ve ana listedeki verilerle karşılaştırır. contains metodu ile isim içerisinde arama yaparak yeni bir liste oluştururuz.


void filtrele(String arananMetin) {
  List sonuclar = [];
  if (arananMetin.isEmpty) {
    sonuclar = tumKullanicilar;
  } else {
    sonuclar = tumKullanicilar
        .where((kullanici) =>
            kullanici.isim.toLowerCase().contains(arananMetin.toLowerCase()))
        .toList();
  }

  setState(() {
    gorunenListe = sonuclar;
  });
}

Burada toLowerCase() kullanarak büyük/küçük harf duyarlılığını ortadan kaldırdık. where metodu, ana liste üzerinde bir döngü kurarak koşulu sağlayan öğeleri yeni bir listeye ekler.

Adım 4: Arayüzü (UI) Tasarlama ve TextField Entegrasyonu

Kullanıcının arama yapabilmesi için bir TextField ve sonuçları göstermek için bir ListView.builder kullanacağız. onChanged parametresi, her harf girişinde filtreleme fonksiyonunu tetikler.


@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: Text("Kullanıcı Ara")),
    body: Column(
      children: [
        TextField(
          controller: aramaController,
          onChanged: (deger) => filtrele(deger),
          decoration: InputDecoration(labelText: "İsim ile ara"),
        ),
        Expanded(
          child: ListView.builder(
            itemCount: gorunenListe.length,
            itemBuilder: (context, index) {
              return ListTile(
                title: Text(gorunenListe[index].isim),
                subtitle: Text(gorunenListe[index].email),
              );
            },
          ),
        ),
      ],
    ),
  );
}

Expanded widget'ı, ListView'un ekranın geri kalanını kaplamasını sağlar. ListView.builder ise sadece ekranda görünen öğeleri oluşturarak yüksek performanslı bir kaydırma deneyimi sunar.

Yöntemlerin Karşılaştırılması

Yöntem Avantajı Dezavantajı
Yerel List Filtreleme Hızlı, basit, bağımlılık yok Çok büyük verilerde yavaşlayabilir
Debounce (Bekletme) Performanslı, işlemciyi yormaz Kod karmaşıklığını artırır

Kritik Güvenlik Uyarısı: Eğer arama verilerini bir API üzerinden çekiyorsanız, kullanıcının girdiği metni mutlaka "sanitize" etmeli ve API tarafında SQL Injection veya XSS saldırılarına karşı önlem almalısınız. Asla doğrudan kullanıcıdan gelen veriyi veritabanı sorgusunda ham olarak kullanmayın.

Adım 5: Performans İyileştirmesi (Debounce Kullanımı)

Eğer listeniz binlerce öğeden oluşuyorsa, her tuş vuruşunda filtreleme yapmak uygulamanın donmasına neden olabilir. Bu durumu önlemek için easy_debounce gibi paketler veya basit bir Timer kullanarak arama işlemini geciktirebilirsiniz.


import 'dart:async';

Timer? _debounce;

void filtreleDebounced(String metin) {
  if (_debounce?.isActive ?? false) _debounce!.cancel();
  _debounce = Timer(const Duration(milliseconds: 500), () {
    filtrele(metin);
  });
}

Bu yöntem, kullanıcı yazmayı bıraktıktan 500 milisaniye sonra filtrelemeyi çalıştırır. Bu sayede gereksiz işlem yükünden kurtulmuş olursunuz.

Sıkça Sorulan Sorular

Filtreleme işlemi büyük harf/küçük harf duyarlı mı?

Hayır, kodumuzda toLowerCase() metodunu kullanarak her iki tarafı da küçük harfe çevirdik, böylece arama duyarsız hale geldi.

Arama sonuçları boş gelirse ne yapmalıyım?

gorunenListe.isEmpty kontrolü yaparak kullanıcıya "Sonuç bulunamadı" şeklinde bir Text veya Icon gösterebilirsiniz.

Bu yöntem API'den gelen verilerde çalışır mı?

Evet, ancak veriyi initState yerine API'den çektikten sonra setState ile güncellemeniz gerekir.

Neden ListView yerine ListView.builder kullanmalıyım?

ListView.builder, verileri tembel (lazy) yükleme yöntemiyle oluşturur. Binlerce öğeli bir listede sadece ekranda olanları render eder, bu da bellek kullanımını optimize eder.

Arama çubuğunu nasıl temizleyebilirim?

aramaController.clear() metodunu çağırarak ve ardından filtrele("") fonksiyonunu çalıştırarak listeyi sıfırlayabilirsiniz.

Gelişmiş Filtreleme Senaryoları: Çoklu Kriterlerle Arama

Basit bir metin tabanlı aramanın ötesine geçmek istediğinizde, kullanıcılarınızın verileri kategorilere, tarihlere veya sayısal değerlere göre filtrelemesini sağlamanız gerekebilir. Bu durum, arama mantığınızı tek bir String kontrolünden, çoklu koşullu bir yapıya dönüştürmenizi gerektirir.

Örneğin, bir e-ticaret uygulamasında ürünleri hem isme göre hem de fiyat aralığına göre filtrelemek için aşağıdaki yaklaşımı kullanabilirsiniz:

List filterProducts(String query, double maxPrice) {
  return allProducts.where((product) {
    final nameMatch = product.name.toLowerCase().contains(query.toLowerCase());
    final priceMatch = product.price  item.contains('El')).toList();
    
    expect(result, ['Elma']);
    expect(result.length, 1);
  });
}

Yaygın Hata: Liste Referansları

Filtreleme yaparken en çok yapılan hata, orijinal listeyi doğrudan filtreleyip üzerine yazmaktır. Bu, verinin kalıcı olarak kaybolmasına neden olur. Her zaman orijinal veriyi (source of truth) ayrı bir değişkende tutmalı ve filtreleme sonucunu yeni bir listeye atamalısınız. List.from() veya List.toList() metodlarını kullanarak verinin kopyası üzerinde işlem yaptığınızdan emin olun.

İpucu: Eğer uygulamanızda çok büyük veri setleri (10.000+ öğe) ile çalışıyorsanız, filtreleme işlemini ana iş parçacığında (UI thread) yapmak yerine compute fonksiyonu ile arka planda (Isolate) gerçekleştirerek uygulamanın donmasını engelleyebilirsiniz.

Sonuç

Flutter ile liste görünümünde arama filtreleme yapmak, yukarıda adım adım incelediğimiz üzere oldukça yalın bir süreçtir. Doğru veri yapısını kurmak, setState ile durumu yönetmek ve performans için Debounce tekniklerini uygulamak, profesyonel bir mobil uygulama geliştirme sürecinin temel taşlarıdır. Bir sonraki adım olarak, bu filtreleme mantığını Provider veya Bloc gibi durum yönetimi kütüphaneleriyle daha modüler bir yapıya taşımayı deneyebilirsiniz.

Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Üretim ortamındaki uygulamalarınızda, verilerin güvenliği ve performans optimizasyonu için projenizin özel ihtiyaçlarına göre ek güvenlik katmanları eklemeyi unutmayın.

Bu yazıya tepkinizi paylaşın:
Kerem Tekin

Teknoloji ve yazılım kullanımı üzerine pratik kılavuzlar hazırlıyorum. Karmaşık dijital araçları, herkesin hızlıca öğrenebileceği sade rehberler haline getirmekte uzmanım.

Yorumlar (0)

Yorum Yaz