Riverpod — Flutter için derlenmiş bir durum ve bağımlılık yöneticisi, 2021 yılında Remi Rousselet tarafından Provider'ın halefi olarak oluşturuldu. Riverpod, Provider'ın temel sorunlarını çözer: derleme zamanı denetimi eksikliği, BuildContext bağımlılığı ve ProviderNotFoundException karmaşıklığı.pub.dev'a göre, paket 5 binden fazla beğeni aldı ve yeni projelerde Provider'ı aktif olarak değiştiriyor.
Ana Noktalar
Riverpod, sağlayıcı tanımlarını güvenli Dart koduna derleyen, Flutter için bir durum yönetimi ve bağımlılık enjeksiyon kütüphanesidir. Provider'ın aksine, Riverpod sağlayıcıları BuildContext'e bağlı değildir: global olarak veya ProviderScope içinde oluşturulurlar ve her yerden erişilebilirler. Derleyici, derleme zamanında türleri, bağımlılıkları ve sağlayıcı grafiğinin bütünlüğünü denetleyerek ProviderNotFoundException gibi çalışma zamanı hatalarını ortadan kaldırır.
Riverpod, test için override modelini kullanır: her sağlayıcı, alt sınıflar oluşturmadan veya arayüzleri mocklamadan ProviderScope.overrideWith aracılığıyla geçersiz kılınabilir. Bu, testleri izole hale getirir: her test, tamamen kontrol edilen bağımlılık grafiğinin kendi kopyasını alır.
Flutter Community Survey 2025'e göre, Riverpod popülerlikte Provider ve BLoC'tan sonra üçüncü sırada yer alıyor. Ancak Riverpod en hızlı büyüyen pakettir: 2024'te +120% kurulum. Ana nedenler: derleme zamanı güvenliği, ProviderNotFoundException olmaması, AsyncValue aracılığıyla yerleşik asenkron destek.
Riverpod 8 tür sağlayıcı sunar, her biri belirli bir senaryo için: Provider (sabit/hizmet), StateProvider (ilkel durum), StateNotifierProvider (StateNotifier ile karmaşık mantık), ChangeNotifierProvider (Provider'dan geçiş için), FutureProvider (asenkron veri, tek seferlik), StreamProvider (reaktif akış), NotifierProvider (yeni API, Flutter 3.10+) ve AsyncNotifierProvider (asenkron Notifier).
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
return CounterNotifier();
});
class CounterNotifier extends StateNotifier<int> {
CounterNotifier() : super(0);
void increment() => state++;
void decrement() => state--;
}
class CounterScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Text('$count');
}
}ProviderRef — diğer sağlayıcılara erişmek için her sağlayıcıya iletilen nesne. ref.watch — değişikliklere abonelik, ref.read — tek seferlik okuma, ref.invalidate — önbellek sıfırlama. ProviderRef, Provider'ın BuildContext'ini değiştirir: herhangi bir sağlayıcı, widget ağacına erişmeden diğer sağlayıcıları okuyabilir. Bu, UI katmanının dışında bir bağımlılık grafiği oluşturmayı sağlar.
ProviderScope — Riverpod'un çalışması için zorunlu olan kök widget. ProviderScope tüm sağlayıcıları depolar, yaşam döngülerini yönetir ve değerleri önbelleğe alır. ProviderScope olmadan uygulama ProviderNotFoundException ile çöker. ProviderScope iç içe geçebilir — iç içe bir kapsam üst sağlayıcıları geçersiz kılar ve test ve özellik izolasyonu için kullanılır.
AsyncValue — asenkron durumu temsil etmek için Riverpod'un sealed sınıfı. AsyncValue'un üç çeşidi vardır: AsyncData (başarılı veri), AsyncError (hata), AsyncLoading (yükleniyor). loading/error/data arasında manuel olarak geçiş yapmak yerine, her FutureProvider veya StreamProvider otomatik olarak AsyncValue döndürür ve widget ref.watch aracılığıyla üç durumu da işler.
final userProvider = FutureProvider((ref) async {
final api = ref.watch(apiProvider);
return await api.fetchUser();
});
class UserScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final userAsync = ref.watch(userProvider);
return userAsync.when(
data: (user) => UserWidget(user),
error: (e, _) => ErrorWidget(e.toString()),
loading: () => CircularProgressIndicator(),
);
}
}AsyncValue.when — üç durumun tümünü desen eşleme için bir yöntem. Derleyici, üç durumun da ele alındığını denetler — loading veya error'u unutursanız, kod derlenmez. AsyncValue.whenData — yalnızca veri için (loading/error gerekli değilse). AsyncValue.guard — istisnaları AsyncError'a dönüştürmek için try-catch sarmalayıcısı. keepAlive — sağlayıcı önbelleğinin kapsam dışına çıktığında yok edilmesini önleyen bir bayrak.
Kod oluşturma — Riverpod 2.0+'ın temel bir özelliği. Bir işlevdeki @riverpod notasyonu, doğru tür, yeniden düzenleme desteği ve otomatik tamamlama ile otomatik olarak bir sağlayıcı oluşturur. Kod oluşturma riverpod_generator ve build_runner kullanır. Geliştirici saf bir işlev yazar ve geri kalan her şey — türler, sınıflar, fabrika yapıcıları — otomatik olarak oluşturulur.
@riverpod
String helloWorld(HelloWorldRef ref) {
return 'Hello World';
}
// Oluşturuldu: final helloWorldProvider = Provider((ref) => 'Hello World');
@riverpod
class Counter extends _$Counter {
int build() => 0;
void increment() => state++;
}Notifier — kod oluşturma ile değişebilir durum için yeni API. Notifier, bir build() yöntemi ve durum değiştirme yöntemleri olan bir sınıftır. StateNotifier'ın aksine, Notifier ayrı bir durum sınıfı gerektirmez ve getter/setter aracılığıyla state'e doğrudan erişim sağlar. Riverpod, @riverpod ile notasyon eklenmiş her Notifier sınıfı için otomatik olarak NotifierProvider oluşturur.
build_runner: kod oluşturma dart run build_runner build komutuyla çalıştırılır. Oluşturulan dosyalar .g.dart sonekine sahiptir ve kaynak koduna aktarılır. Notasyonlar veya sağlayıcı türleri değiştiğinde, kod oluşturmanın yeniden çalıştırılması gerekir. Riverpod 2.x, tüm yeni projeler için kod oluşturmayı önerir — manuel sağlayıcı oluşturma eskimektedir.
Temel farklar Riverpod ve Provider arasında: BuildContext'ten bağımsızlık, derleme zamanı güvenliği, yerleşik asenkron destek, otomatik önbellekleme ve override aracılığıyla test. Provider, duruma erişmek için BuildContext gerektirir (context.watch, context.read), Riverpod WidgetRef ve global olarak bildirilen sağlayıcıları kullanır.
| Özellik | Provider | Riverpod |
|---|---|---|
| BuildContext bağımlılığı | Evet | Hayır |
| Derleme zamanı denetimi | Hayır | Evet (@riverpod ile) |
| ProviderNotFoundException | Çalışma zamanı | İmkansız |
| Asenkron | Manuel | AsyncValue (yerleşik) |
| Test | Provider'da sarmalayıcı | ProviderScope.overrideWith |
| Önbellekleme | Hayır | Otomatik + keepAlive |
Provider'dan geçiş: Riverpod, yeniden yazmadan mevcut ChangeNotifier'ı kullanmak için ChangeNotifierProvider.adaptive'yi destekler. Kademeli geçiş: önce yeni özellikler Riverpod ile yazılır, ardından eski Provider örnekleri bir adaptör aracılığıyla Riverpod sağlayıcılarıyla değiştirilir. Her iki paket bir projede birlikte var olabilir ve geliştirmeyi dondurmadan geçişe izin verir.
Riverpod test etme ProviderScope.overrideWith üzerine kuruludur. Her sağlayıcı, mock veya DI kapsayıcıları olmadan bir test ProviderScope içinde geçersiz kılınır. ProviderContainer — Flutter olmadan testler için izole bir ortam (saf Dart), widget oluşturmadan sağlayıcıları test etmeye izin verir.
import 'package:flutter_test/flutter_test.dart';
import 'package:riverpod/riverpod.dart';
void main() {
test('Counter increments correctly', () {
final container = ProviderContainer();
container.read(counterProvider.notifier).increment();
expect(container.read(counterProvider), 1);
});
testWidgets('UI updates on increment', (tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [counterProvider.overrideWithValue(5)],
child: CounterScreen(),
),
);
expect(find.text('5'), findsOneWidget);
});
}ProviderContainer — Flutter'sız. Widget'sız sağlayıcıların birim testleri için ProviderContainer kullanın. overrideWithValue — bir sağlayıcıyı belirli bir değerle değiştirme. overrideWith — bir sağlayıcı fabrikasıyla değiştirme (hizmetleri mocklamak için). autodispose — testlerde, container.dispose() kullanarak sağlayıcının kapsam dışına çıktığında yok edildiğini doğrulayın.
Sıkça Sorulan Sorular
Riverpod, global sağlayıcılar, AsyncValue ve kod oluşturma ile bir durum yönetimi kütüphanesidir. BLoC, Event → Stream → State ile bir mimari desendir. Riverpod öğrenmesi daha kolaydır ve @riverpod notasyonları aracılığıyla daha iyi DX sağlar. BLoC, BlocObserver aracılığıyla sıkı iş mantığı izolasyonu ve Olay izleme sağlar. Seçim proje paradigmasına bağlıdır: Riverpod Provider'a daha yakındır, BLoC — reaktif akışlara.
Autodispose, kimse abone olmadığında bir sağlayıcıyı otomatik olarak yok etme mekanizmasıdır. Varsayılan olarak, tüm Riverpod sağlayıcıları autodispose yapar: bir widget ağaçtan çıktığında, sağlayıcı bellekten kaldırılır. keepAlive — her zaman yaşaması gereken sağlayıcılar (API istemcileri, depolar, ayarlar) için autodispose'u devre dışı bırakan bir bayrak. Bu, bellek sızıntılarını önler — kullanılmayan sağlayıcılar otomatik olarak yok edilir.
ref.invalidate — sağlayıcı önbelleğini zorla sıfırlayan bir yöntem. invalidate'den sonra, sonraki okumada sağlayıcı yeniden oluşturulur: FutureProvider asenkron işlevi yeniden yürütür, StreamProvider akışa yeniden abone olur. Veri yenilemeyi zorlamak için invalidate kullanın (çek-yenile, kullanıcı değişikliği). ref.refresh — invalidate + okuma kombinasyonu: tek bir işlemde sıfırlar ve hemen yeni değeri okur.
Evet. Riverpod 1.x yalnızca kod oluşturma olmadan çalışır — sağlayıcılar Provider(), StateNotifierProvider(), FutureProvider() vb. kullanılarak manuel olarak oluşturulur. Riverpod 2.x her iki yaklaşımı da destekler. Kod oluşturma olmadan daha fazla tekrar eden kod vardır ancak build_runner ve dart run build_runner build'e bağımlılık yoktur. Küçük projeler (30 sağlayıcıya kadar) için manuel oluşturma haklıdır; büyük projeler için kod oluşturma zorunludur.
Family — harici bir parametre kabul eden bir sağlayıcı değiştiricisi. Örneğin, userProvider(123) — ID 123 olan bir kullanıcıyı yükleyen sağlayıcı. Family sağlayıcıları, her benzersiz parametre için sonucu ayrı ayrı önbelleğe alır. Her öğenin kimlikle yüklendiği öğe listeleri için Family kullanın. Family değiştiricisi tüm sağlayıcı türleri için kullanılabilir: Provider.family, FutureProvider.family, StreamProvider.family.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.