miniriverpod के पीछे के डिज़ाइन सिद्धांत।
पैकेज जानबूझकर features को सीमित करता है ताकि व्यवहार स्पष्ट रहे: args के आधार पर provider पहचान, Scope के माध्यम से scoped injection, और पूर्वानुमेय disposal semantics.
Riverpod की तुलना में क्या बदलता है
Generated family classes और implicit notifier channels के बजाय, miniriverpod subclass + args + explicit invoke को प्राथमिकता देता है.
Provider identity
runtimeType + args hash
family alternative
Provider / AsyncProvider की subclass बनाएँ और super.args((...)) पास करें.
DI fallback
Scope<T>.required + overrideWithValue
यह क्यों महत्वपूर्ण है
सामान्य Dart constructors से equality और overrides के बारे में तर्क किया जा सकता है, जिससे debugging और tests सीधे रहते हैं.
args के साथ Provider पहचान
args provider key को परिभाषित करता है, इसलिए समान args का मतलब ProviderContainer के भीतर वही cache entry होता है।
Identity rule
व्यावहारिक परिणाम
- अलग family type की आवश्यकता नहीं है.
- हर argument के लिए override provider instances बनाकर किया जाता है.
- पूर्वानुमेय caching के लिए args को स्थिर और immutable रखें.
उदाहरण: family-जैसा provider + Scope fallback
constructor argument को identity की तरह उपयोग करें और Scope के माध्यम से एक fallback instance inject करें।
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);
}
}
// Inject
ProviderScope(
overrides: [
ProductProvider.fallback.overrideWithValue(ProductProvider(search: 'jeans')),
],
child: const App(),
);