Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce geliştirme ortamınızın güncel olduğundan emin olmalısınız. 2026 yılı itibarıyla Flutter 3.x ve üzeri sürümler, Null Safety (Boş Güvenlik) ve gelişmiş state management (durum yönetimi) kütüphaneleri ile stabil çalışmaktadır.
- Flutter SDK (3.24 veya üzeri)
- Dart 3.5+
- VS Code veya Android Studio
- HTTP istekleri için 'dio' paketi
- State yönetimi için 'flutter_bloc' veya 'riverpod'
Öncelikle projenizi oluşturun ve pubspec.yaml dosyanıza gerekli bağımlılıkları ekleyin. Çok katmanlı mimari için projenizi data, domain ve presentation klasörlerine ayırmanız gerekecek.
Veri Katmanı (Data Layer) Tasarımı
Veri katmanı, dış dünyadan (API veya yerel veritabanı) gelen ham veriyi karşılayan bölümdür. Burada Model sınıflarımızı ve Repository implementasyonlarımızı oluştururuz. Güvenlik açısından, API anahtarlarınızı asla doğrudan kod içerisinde tutmayın; .env dosyaları kullanarak çevresel değişkenler ile yönetin.
// lib/data/models/news_model.dart
class NewsModel {
final String title;
final String content;
NewsModel({required this.title, required this.content});
factory NewsModel.fromJson(Map json) {
return NewsModel(
title: json['title'] ?? 'Başlıksız',
content: json['content'] ?? '',
);
}
}
Yukarıdaki kod bloğu, API'den gelen JSON verisini güvenli bir şekilde nesneye dönüştürmemizi sağlar. fromJson metodu içerisinde null kontrolü yaparak uygulamanın çökmesini engelliyoruz.
Domain Katmanı: İş Mantığı ve Soyutlama
Domain katmanı, uygulamanın kalbidir ve hiçbir dış kütüphaneye bağımlı olmamalıdır. Burada Entity sınıflarını ve Repository arayüzlerini (abstract class) tanımlarız. Bu, veri kaynağını ileride değiştirseniz bile iş mantığınızın etkilenmemesini sağlar.
// lib/domain/repositories/news_repository.dart
abstract class NewsRepository {
Future getNews();
}
Bu soyut sınıf, uygulamanın geri kalanına "haberleri getirmek için bir metodum var" der ancak bu haberlerin internetten mi yoksa yerel veritabanından mı geleceği ile ilgilenmez.
Sunum Katmanı (Presentation Layer)
Sunum katmanı, UI (Kullanıcı Arayüzü) ve durumu yöneten bloklardan oluşur. Haber akışını ekrana basarken Bloc kullanarak verinin yükleniyor, başarılı veya hatalı olduğu durumları yönetiriz. Bu, kullanıcı deneyimini (UX) doğrudan etkileyen kritik bir adımdır.
// lib/presentation/bloc/news_bloc.dart
class NewsBloc extends Bloc {
final GetNewsUseCase getNewsUseCase;
NewsBloc(this.getNewsUseCase) : super(NewsInitial()) {
on((event, emit) async {
emit(NewsLoading());
try {
final news = await getNewsUseCase();
emit(NewsLoaded(news));
} catch (e) {
emit(NewsError("Haberler yüklenemedi."));
}
});
}
}
Bu yapı sayesinde UI katmanı, veri çekme sürecinin karmaşıklığından kurtulur ve sadece NewsState'e göre ekranda ne göstereceğine odaklanır.
Mimari Yöntemlerin Karşılaştırılması
Çok katmanlı mimariyi uygularken farklı yaklaşımlar mevcuttur. Aşağıdaki tablo, projelerinizde tercih edebileceğiniz mimari yapıların bir özetidir.
| Mimari Yaklaşım | Avantajı | Dezavantajı |
|---|---|---|
| Clean Architecture | Yüksek test edilebilirlik | Başlangıçta karmaşık yapı |
| MVVM | UI ile mantık ayrımı | Büyük projelerde ölçekleme sorunu |
| MVC | Hızlı geliştirme | Kodun spagettiye dönme riski |
Haber Akışı Arayüzü ve Liste Yönetimi
Haber akışını liste olarak göstermek için ListView.builder kullanmak, performans açısından en doğru yöntemdir. Bu yöntem, sadece ekranda görünen öğeleri oluşturarak bellek kullanımını optimize eder.
// lib/presentation/pages/news_page.dart
ListView.builder(
itemCount: newsList.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(newsList[index].title),
subtitle: Text(newsList[index].content),
);
},
)
Bu basit yapı, newsList verisi güncellendiğinde arayüzü otomatik olarak yeniler. Büyük veri setlerinde ListView.separated kullanarak öğeler arasına ayırıcılar eklemek görsel düzeni artırır.
Kritik Güvenlik Uyarısı: Üretim ortamında (production) API isteklerinizde SSL pinning yöntemini kullanın. Ayrıca, kullanıcıdan gelen verileri veya API'den gelen HTML içeriğini doğrudan
HtmlWidgetgibi bileşenlere aktarırken XSS (Cross-Site Scripting) saldırılarına karşı sanitize etmeyi unutmayın.
Sıkça Sorulan Sorular
Çok katmanlı mimari küçük projeler için gerekli mi?
Küçük projelerde biraz vakit kaybettirebilir ancak projenin büyüme potansiyeli varsa başlangıçta bu yapıyı kurmak, ileride yaşanacak teknik borçları (technical debt) engeller.
State yönetimi için neden Bloc tercih etmeliyim?
Bloc, olay tabanlı yapısı sayesinde uygulamanın durumlarını tahmin edilebilir kılar ve büyük ekiplerle çalışırken kodun standart kalmasını sağlar.
API'den gelen verileri nasıl önbelleğe alırım?
Data katmanında Repository içerisinde shared_preferences veya sqflite kullanarak yerel bir cache mekanizması kurabilirsiniz.
Uygulama neden yavaş çalışıyor olabilir?
Genellikle gereksiz setState tetiklemeleri veya büyük görsellerin optimize edilmeden yüklenmesi performans kaybına yol açar. cached_network_image paketini kullanmanızı öneririm.
Test yazmak zorunlu mu?
Clean Architecture'ın en büyük avantajı test edilebilir olmasıdır. Unit testler ile iş mantığınızı, widget testleri ile arayüzünüzü garanti altına alabilirsiniz.
İleri Seviye Hata Ayıklama ve Loglama Stratejileri
Çok katmanlı mimaride hata ayıklama, verinin hangi katmanda bozulduğunu veya durduğunu tespit etmekle başlar. Karmaşık bir haber akışında, API'den gelen verinin Domain katmanına ulaşmadan önce Data katmanında nasıl dönüştürüldüğünü izlemek için Interceptors kullanımı kritiktir.
Dio kütüphanesi üzerinde bir log interceptor kullanarak, ağ trafiğinizi konsolda detaylıca inceleyebilirsiniz:
final dio = Dio();
dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
print("İstek Gönderiliyor: ${options.path}");
return handler.next(options);
},
onResponse: (response, handler) {
print("Yanıt Alındı: ${response.statusCode}");
return handler.next(response);
},
onError: (DioException e, handler) {
print("Hata Oluştu: ${e.message}");
return handler.next(e);
},
));
Hata Yönetimi İçin "Either" Pattern Kullanımı
Haber akışında ağ hataları veya veri ayrıştırma (parsing) hataları kaçınılmazdır. dartz paketi ile gelen Either yapısı, fonksiyonlarınızın hem hata hem de başarı durumunu tip güvenli bir şekilde döndürmesini sağlar. Bu, UI katmanında try-catch blokları yerine daha temiz bir yapı kurmanıza yardımcı olur.
// Domain katmanında repository tanımı
Future getNews();
// Sunum katmanında kullanımı
final result = await getNewsUseCase();
result.fold(
(failure) => showErrorMessage(failure.message),
(newsList) => updateUI(newsList),
);
Performans Optimizasyonu: Haber Akışında Bellek Yönetimi
Haber uygulamalarında en büyük performans sorunu, yüzlerce görselin yüklendiği listelerin bellek (RAM) tüketimidir. Çok katmanlı mimaride, veriyi Domain katmanında Equatable kullanarak nesne karşılaştırmalarını optimize etmeli ve gereksiz re-render işlemlerinden kaçınmalısınız.
Görsel Önbellekleme ve Liste Optimizasyonu
ListView.builder kullanırken, liste elemanlarının sadece ekranda göründüğünde oluşturulmasını sağlamak için cacheExtent özelliğini yapılandırın. Ayrıca, görseller için cached_network_image kullanarak disk üzerinde önbellekleme yapın:
ListView.builder(
cacheExtent: 500, // Görünür alanın dışındaki 500px'lik kısmı önbelleğe al
itemCount: newsList.length,
itemBuilder: (context, index) {
return CachedNetworkImage(
imageUrl: newsList[index].imageUrl,
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
);
},
);
Ayrıca, büyük JSON verilerini işlerken compute fonksiyonunu kullanarak parse işlemlerini ana thread (UI thread) dışına taşıyabilirsiniz. Bu, haber akışının kaydırılma sırasında takılmasını (jank) engeller.
Future parseNews(String responseBody) {
return compute(_decodeAndMap, responseBody);
}
List _decodeAndMap(String body) {
final parsed = jsonDecode(body).cast();
return parsed.map((json) => News.fromJson(json)).toList();
}
Sonuç
Flutter & Mobil ile çok katmanlı mimari tabanlı haber akışı geliştirmek, başlangıçta zorlayıcı görünse de uzun vadede uygulamanızın kalitesini ve bakım maliyetini optimize eder. Bu rehberdeki adımları takip ederek, 2026 standartlarına uygun, modüler ve güvenli bir uygulama mimarisi kurabilirsiniz.
Bir sonraki adım olarak, uygulamanıza "Pull-to-Refresh" özelliği ekleyebilir veya Firebase Remote Config kullanarak haber kategorilerini dinamik olarak yönetebilirsiniz.
Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Ticari projelerinizde güvenlik açıklarını kapatmak için düzenli olarak bağımlılıklarınızı güncelleyin ve profesyonel sızma testleri gerçekleştirin.


Yorumlar (0)
Yorum Yaz