Flutter API
ProviderScope can own a container ?? receive one externally. Consumer APIs keep WidgetRef access compatible ?? Riverpod-style code.
ProviderScope Ownership
Container ownership changes disposal responsibility.
Internal container
ProviderScope(child: ...) disposes automatically
External container
ProviderScope(container: c, ...) requires c.dispose() by caller
Uncontrolled scope
UncontrolledProviderScope never disposes the container
Common pitfall
?? widget tests, remember ? dispose externally injected ProviderContainer ? avoid pending timer leaks.
Consumer Variants
All options expose WidgetRef; choose by widget style ? ?? state needs.
? root
runApp(const ProviderScope(child: MyApp()));
When ? use each
Consumer: local builder block for small reactive areas.
ConsumerWidget: stateless widget with build(context, ref).
ConsumerStatefulWidget: stateful widget with ref inside ConsumerState.
??: ConsumerStatefulWidget
Use ConsumerState when you need both WidgetRef ? ?? mutable UI state.
home_page.dart
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 internals schedule rebuilds ? post-frame, reducing setState-during-build issues.
Use WidgetRef.watch ?? ? values that should trigger rebuilds.
Keep side effects outside build; use callbacks ? invoke/refresh methods.