Riverpod — manajer state dan dependensi yang dapat dikompilasi untuk Flutter, dibuat oleh Rémi Roussel pada tahun 2021 sebagai penerus Provider. Riverpod memecahkan masalah fundamental Provider: kurangnya pemeriksaan kompilasi, ketergantungan pada BuildContext dan kesulitan dengan ProviderNotFoundException. Menurut data pub.dev, paket ini telah mengumpulkan lebih dari 5 ribu like dan secara aktif menggantikan Provider di proyek-proyek baru.
Poin Utama
Riverpod — sebuah pustaka untuk manajemen state dan injeksi dependensi di Flutter yang mengkompilasi deskripsi provider menjadi kode Dart yang aman. Tidak seperti Provider, provider Riverpod tidak terikat pada BuildContext: mereka dibuat secara global atau di ProviderScope dan dapat diakses dari mana saja. Kompilator memeriksa tipe, dependensi, dan integritas graf provider pada tahap build, menghilangkan kesalahan runtime seperti ProviderNotFoundException.
Riverpod menggunakan model override untuk pengujian: setiap provider dapat ditimpa melalui ProviderScope.overrideWith tanpa perlu membuat subkelas atau mem-mock antarmuka. Ini membuat pengujian menjadi terisolasi: setiap pengujian mendapatkan salinan graf dependensinya sendiri yang sepenuhnya terkontrol.
Menurut Flutter Community Survey 2025, Riverpod menempati posisi ketiga dalam popularitas setelah Provider dan BLoC. Pada saat yang sama, Riverpod adalah paket dengan pertumbuhan tercepat: +120% instalasi pada tahun 2024. Alasan utama: keamanan kompilasi, tidak adanya ProviderNotFoundException, dukungan asinkronisitas bawaan melalui AsyncValue.
Riverpod menyediakan 8 tipe provider, masing-masing untuk skenario tertentu: Provider (konstanta/layanan), StateProvider (state primitif), StateNotifierProvider (logika kompleks dengan StateNotifier), ChangeNotifierProvider (untuk migrasi dari Provider), FutureProvider (data asinkron, sekali), StreamProvider (aliran reaktif), NotifierProvider (API baru, Flutter 3.10+) dan AsyncNotifierProvider (Notifier asinkron).
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 — objek yang diteruskan ke setiap provider untuk mengakses provider lain. ref.watch — berlangganan perubahan, ref.read — pembacaan sekali, ref.invalidate — mereset cache. ProviderRef menggantikan BuildContext dari Provider: provider mana pun dapat membaca provider lain tanpa akses ke pohon widget. Ini memungkinkan pembangunan graf dependensi di luar lapisan UI.
ProviderScope — widget root wajib untuk menjalankan Riverpod. ProviderScope menyimpan semua provider, mengelola siklus hidupnya, dan menyimpan cache nilai. Tanpa ProviderScope, aplikasi akan crash dengan ProviderNotFoundException. ProviderScope dapat bersarang — scope bersarang menimpa provider induk, yang digunakan untuk pengujian dan isolasi fitur.
AsyncValue — kelas sealed Riverpod untuk merepresentasikan state asinkron. AsyncValue memiliki tiga varian: AsyncData (data berhasil), AsyncError (kesalahan), AsyncLoading (memuat). Alih-alih beralih secara manual antara loading/error/data, setiap FutureProvider atau StreamProvider secara otomatis mengembalikan AsyncValue, dan widget menangani ketiga status melalui ref.watch.
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 — metode untuk pencocokan pola ketiga status. Kompilator memeriksa bahwa ketiga kasus telah ditangani — jika loading atau error dilupakan, kode tidak akan dikompilasi. AsyncValue.whenData — hanya untuk data (jika loading/error tidak diperlukan). AsyncValue.guard — pembungkus try-catch untuk mengonversi pengecualian menjadi AsyncError. keepAlive — bendera yang mencegah penghancuran cache provider saat keluar dari cakupan visibilitas.
Pembuatan kode — fitur utama Riverpod 2.0+. Anotasi @riverpod di atas fungsi secara otomatis menghasilkan provider dengan tipe yang benar, dukungan refactoring, dan penyelesaian otomatis. Pembuatan kode menggunakan riverpod_generator dan build_runner. Pengembang menulis fungsi murni, dan sisanya — tipe, kelas, konstruktor factory — dihasilkan secara otomatis.
@riverpod
String helloWorld(HelloWorldRef ref) {
return 'Hello World';
}
// Dihasilkan: final helloWorldProvider = Provider((ref) => 'Hello World');
@riverpod
class Counter extends _$Counter {
int build() => 0;
void increment() => state++;
}Notifier — API baru untuk state yang dapat diubah dengan pembuatan kode. Notifier adalah kelas dengan metode build() dan metode untuk mengubah state. Tidak seperti StateNotifier, Notifier tidak memerlukan kelas state terpisah dan memberikan akses langsung ke state melalui getter/setter. Riverpod secara otomatis menghasilkan NotifierProvider untuk setiap kelas Notifier dengan anotasi @riverpod.
build_runner: pembuatan kode dijalankan dengan perintah dart run build_runner build. File yang dihasilkan memiliki akhiran .g.dart dan diimpor ke kode sumber. Saat mengubah anotasi atau tipe provider, pembuatan kode harus dijalankan ulang. Riverpod 2.x merekomendasikan pembuatan kode untuk semua proyek baru — pembuatan provider secara manual mulai usang.
Perbedaan utama Riverpod dari Provider: independensi dari BuildContext, keamanan kompilasi, kerja bawaan dengan asinkronisitas, caching otomatis dan pengujian melalui override. Provider memerlukan BuildContext untuk mengakses state (context.watch, context.read), Riverpod menggunakan WidgetRef dan provider yang dideklarasikan secara global.
| Karakteristik | Provider | Riverpod |
|---|---|---|
| Ketergantungan pada BuildContext | Ya | Tidak |
| Pemeriksaan kompilasi | Tidak | Ya (melalui @riverpod) |
| ProviderNotFoundException | Runtime | Tidak mungkin |
| Asinkronisitas | Manual | AsyncValue (bawaan) |
| Pengujian | Pembungkus di Provider | ProviderScope.overrideWith |
| Caching | Tidak | Otomatis + keepAlive |
Migrasi dari Provider: Riverpod mendukung ChangeNotifierProvider.adaptive untuk menggunakan ChangeNotifier yang ada tanpa menulis ulang. Migrasi bertahap: pertama fitur baru ditulis dengan Riverpod, kemudian Provider lama diganti dengan provider Riverpod melalui adaptor. Kedua paket dapat hidup berdampingan dalam satu proyek, memungkinkan migrasi tanpa menghentikan pengembangan.
Menguji Riverpod didasarkan pada ProviderScope.overrideWith. Setiap provider ditimpa di dalam ProviderScope pengujian tanpa mock dan container DI. ProviderContainer — lingkungan terisolasi untuk pengujian tanpa Flutter (Dart murni), memungkinkan pengujian provider tanpa merender widget.
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 — tanpa Flutter. Gunakan ProviderContainer untuk pengujian unit provider tanpa widget. overrideWithValue — mengganti provider dengan nilai tertentu. overrideWith — mengganti dengan pabrik provider (untuk mem-mock layanan). autodispose — dalam pengujian, periksa apakah provider dihancurkan saat keluar dari cakupan visibilitas, dengan container.dispose().
Pertanyaan yang Sering Diajukan
Riverpod — pustaka manajemen state dengan provider global, AsyncValue dan pembuatan kode. BLoC — pola arsitektur dengan Event → Stream → State. Riverpod lebih mudah dipelajari dan memiliki DX yang lebih baik melalui anotasi @riverpod. BLoC memberikan isolasi ketat logika bisnis dan pelacakan Event melalui BlocObserver. Pilihan tergantung pada paradigma proyek: Riverpod lebih dekat ke Provider, BLoC — ke aliran reaktif.
Autodispose — mekanisme penghancuran otomatis provider ketika tidak ada yang berlangganan. Secara default, semua provider Riverpod adalah autodispose: saat widget keluar dari pohon, provider dihapus dari memori. keepAlive — bendera yang menonaktifkan autodispose untuk provider yang harus selalu hidup (klien API, repositori, pengaturan). Ini mencegah kebocoran memori — provider yang tidak digunakan dihancurkan secara otomatis.
ref.invalidate — metode yang memaksa mereset cache provider. Setelah invalidate, provider dibuat ulang pada pembacaan berikutnya: FutureProvider menjalankan ulang fungsi async, StreamProvider berlangganan ulang ke aliran. Gunakan invalidate untuk pembaruan data paksa (pull-to-refresh, pergantian pengguna). ref.refresh — kombinasi invalidate + pembacaan: mereset dan langsung membaca nilai baru dalam satu operasi.
Ya. Riverpod 1.x hanya bekerja tanpa pembuatan kode — provider dibuat secara manual melalui Provider(), StateNotifierProvider(), FutureProvider() dll. Riverpod 2.x mendukung kedua pendekatan. Tanpa pembuatan kode ada lebih banyak boilerplate, tetapi tidak ada ketergantungan pada build_runner dan dart run build_runner build. Untuk proyek kecil (hingga 30 provider), pembuatan manual dapat dibenarkan, untuk proyek besar, pembuatan kode wajib.
Family — pengubah provider yang menerima parameter eksternal. Misalnya, userProvider(123) — provider yang memuat pengguna dengan ID 123. Family provider menyimpan cache hasil untuk setiap parameter unik secara terpisah. Gunakan Family untuk daftar elemen di mana setiap elemen dimuat berdasarkan ID. Pengubah Family tersedia untuk semua tipe provider: Provider.family, FutureProvider.family, StreamProvider.family.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga