Consumer constructor

const Consumer({
  1. Key? key,
  2. required ConsumerBuilder builder,
  3. Widget? child,
})

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 the body 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});