miniriverpod 背後的設計原則。
這個套件刻意縮小功能範圍,以維持行為清楚:透過 args 定義 provider 識別、Scope 注入,以及可預測的釋放語意。
與 Riverpod 相比有什麼改變
相較於生成的 family 類別與隱式 notifier 通道,miniriverpod 更偏好 subclass + args + 顯式 invoke。
provider 識別
runtimeType + args 雜湊
family 替代方案
繼承 Provider / AsyncProvider,並傳入 super.args((...))
DI 回退
Scope<T>.required + overrideWithValue
為什麼這很重要
你可以直接從 Dart 建構函式推理相等性與覆寫規則,這會讓除錯與測試更直觀。
使用 args 的 Provider 識別
args 定義 provider key,因此相同 args 在 ProviderContainer 中就代表同一個快取條目。
識別規則
實際影響
- 不需要專用的 family 型別。
- 依參數覆寫是透過建立 provider 實例完成。
- 讓 args 保持穩定且不可變,快取行為才會可預測。
範例:類 family 的 provider + Scope 回退
把建構函式參數當作識別,並透過 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);
}
}
// 注入
ProviderScope(
overrides: [
ProductProvider.fallback.overrideWithValue(ProductProvider(search: 'jeans')),
],
child: const App(),
);
Scope 讓依賴連線保持顯式,也更便於測試。
overrideWithValue 可以針對每個 provider 實例運作,包括基於 args 的實例。
使用子類別 + args 不會改變 autoDispose 行為。