Prinsip desain di balik miniriverpod.
Paket ini sengaja membatasi fitur agar perilaku tetap eksplisit: identitas provider berdasarkan args, injeksi terlingkup, dan semantik pelepasan yang dapat diprediksi.
Apa yang Berubah dari Riverpod
Alih-alih kelas family hasil generasi dan kanal notifier implisit, miniriverpod lebih memilih subclass + args + invoke eksplisit.
Identitas provider
runtimeType + args hash
Alternatif family
Turunkan Provider / AsyncProvider sebagai subclass dan teruskan super.args((...))
Cadangan DI
Scope<T>.required + overrideWithValue
Mengapa ini penting
Anda dapat menalar kesetaraan dan override dari konstruktor Dart biasa, yang membuat debugging dan pengujian tetap sederhana.
Identitas provider dengan args
args mendefinisikan kunci provider, jadi args yang sama berarti entri cache yang sama di dalam ProviderContainer.
Aturan identitas
Konsekuensi praktis
- Tidak diperlukan tipe family khusus.
- Override per argumen dilakukan dengan membuat instance provider.
- Pertahankan args tetap stabil dan immutable untuk caching yang dapat diprediksi.
Contoh: provider mirip family + cadangan Scope
Gunakan argumen konstruktor sebagai identitas dan injeksikan instance cadangan melalui Scope.
class ProductProvider extends AsyncProvider<List<Product>> {
ProductProvider({this.search = ''}) : super.args((search,));
final String search;
static final fallback = Scope<ProductProvider>.required('product.fallback');
@override
FutureOr<List<Product>> build(ref) async {
final api = ref.watch(productsApiProvider);
return api.search(q: search);
}
}
// Injeksi
ProviderScope(
overrides: [
ProductProvider.fallback.overrideWithValue(ProductProvider(search: 'jeans')),
],
child: const App(),
);
Langkah Berikutnya
Provider dan Pembacaan
Lihat pola konkret untuk watch/read/listen dan AsyncProvider.future.
Buka Provider