Flutter 整合與明確的 container 所有權。
ProviderScope 可以自己持有 container,也可以接收外部 container。Consumer 系列 API 讓 WidgetRef 的存取方式與 Riverpod 風格程式碼保持相容。
ProviderScope 所有權
container 所有權會改變 dispose 的責任歸屬。
內部 container
ProviderScope(child: ...) 會自動釋放
外部 container
ProviderScope(container: c, ...) 需要由呼叫端執行 c.dispose()
未受控的 scope
UncontrolledProviderScope 永遠不會釋放 container
常見誤區
在 widget test 中,記得釋放外部注入的 ProviderContainer,以避免留下待處理的 timer leak。
Consumer 變體
所有選項都會暴露 WidgetRef;依據 widget 風格與本地狀態需求選擇即可。
應用程式根目錄
各自適用時機
Consumer:適合小範圍 reactive 區域的區域性 builder 區塊。
ConsumerWidget:帶有 build(context, ref) 的 stateless widget。
ConsumerStatefulWidget:在 ConsumerState 內持有 ref 的 stateful widget。
範例:ConsumerStatefulWidget
當你同時需要 WidgetRef 和本地可變 UI 狀態時,使用 ConsumerState。
class HomePage extends ConsumerStatefulWidget {
const HomePage({super.key});
@override
ConsumerState<HomePage> createState() => _HomePageState();
}
class _HomePageState extends ConsumerState<HomePage> {
bool expanded = false;
@override
Widget build(BuildContext context) {
final user = ref.watch(currentUser);
return Column(
children: [
Text('$user'),
Switch(
value: expanded,
onChanged: (v) => setState(() => expanded = v),
),
],
);
}
}
Consumer 的內部會把重建排程到 post-frame,從而減少 build 期間呼叫 setState 的問題。
WidgetRef.watch 只用於那些應該觸發重建的值。
把副作用放在 build 之外,改用 callback 以及 invoke / refresh 方法。