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 行為。

下一步

Providers 與讀取

查看 watch/read/listen 以及 AsyncProvider.future 的具體模式。

開啟 Providers

變更

使用 mutation token、mutate 和 ref.invoke 來實作狀態更新。

開啟變更