Consumer constructor
Build a widget tree while listening to providers.
Consumer's main use-case is for reducing the number of rebuilt widgets. when a provider changes.
As an example, consider:
@riverpod
Future<User> fetchUser(Ref ref) async {
// ...
}
Normally, we would use a ConsumerWidget as followed:
class Example extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(title: Text('User')),
body: switch (ref.watch(userProvider) {
AsyncValue(:final value?) => Text(value.name),
AsyncValue(hasError: true) => Text('Error'),
_ => CircularProgressIndicator(),
},
}
}
However, this would rebuild the entire Scaffold
when the user changes.
If we are looking to reduce this, have two options:
- Extract the
body
into a separate ConsumerWidget. Then only thebody
will rebuild. This is the recommended approach, but is a bit more verbose. - Use Consumer to only rebuild the
body
when the user changes. This is less recommended, but avoids creating a new widget.
Using Consumer, the resulting code would look like:
class Example extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('User')),
body: Consumer(
builder: (context, ref, child) {
return switch (ref.watch(userProvider) {
AsyncValue(:final value?) => Text(value.name),
AsyncValue(hasError: true) => Text('Error'),
_ => CircularProgressIndicator(),
};
}),
);
}
}
Performance considerations
To optimize performance by avoiding unnecessary network requests and pausing unused streams, Consumer will temporarily stop listening to providers when the widget stops being visible.
This is determined using TickerMode.of, and will invoke ProviderSubscription.pause on all currently active subscriptions.
See also:
- ConsumerWidget, a base-class for widgets that wants to listen to providers.
- child, a way to optimize the widget tree by passing a child widget that won't rebuild when the provider changes.
Implementation
const Consumer({super.key, required this.builder, this.child});