Consumer5<A, B, C, D, E> class

Obtain Provider<T> from its ancestors and pass its value to builder.

The widget Consumer doesn't do any fancy work. It just calls Provider.of in a new widget, and delegate its build implementation to builder.

builder must not be null and may be called multiple times (such as when provided value change).

The wiget Consumer has two main purposes:

  • It allows obtaining a value from a provider when we don't have a BuildContext that is a descendant of the said provider, and therefore cannot use Provider.of.

Such scenario typically happens when the widget that creates the provider is also one of its consumers, like in the following example:

@override
Widget build(BuildContext context) {
  return ChangeNotifierProvider(
    builder: (_) => Foo(),
    child: Text(Provider.of<Foo>(context).value),
  );
}

This example will throw a ProviderNotFoundError, because Provider.of is called with a BuildContext that is an ancestor of the provider.

Instead, we can use the Consumer widget, that will call Provider.of with its own BuildContext.

Using Consumer, the previous example will become:

@override
Widget build(BuildContext context) {
  return ChangeNotifierProvider(
    builder: (_) => Foo(),
    child: Consumer<Foo>(
      builder: (_, foo, __) => Text(foo.value),
    },
  );
}

This won't throw a ProviderNotFoundError and will correctly build the Text. It will also update the Text whenever the value foo changes.

  • It helps with performance optimisation by having more granular rebuilds.

Unless listen: false is passed to Provider.of, it means that the widget associated to the BuildContext passed to Provider.of will rebuild whenever the obtained value changes.

This is the expected behavior, but sometimes it may rebuild more widgets than needed.

Here's an example:

 @override
 Widget build(BuildContext context) {
   return FooWidget(
     child: BarWidget(
       bar: Provider.of<Bar>(context),
     ),
   );
 }

In such code, only BarWidget depends on the value returned by Provider.of. But when Bar changes, then both BarWidget and FooWidget will rebuild.

Ideally, only BarWidget should be rebuilt. And to achieve that, one solution is to use Consumer.

To do so, we will wrap only the widgets that depends on a provider into a Consumer:

 @override
 Widget build(BuildContext context) {
   return FooWidget(
     child: Consumer<Bar>(
       builder: (_, bar, __) => BarWidget(bar: bar),
     ),
   );
 }

In this situation, if Bar were to update, only BarWidget would rebuild.

But what if it was FooWidget that depended on a provider? Example:

 @override
 Widget build(BuildContext context) {
   return FooWidget(
     foo: Provider.of<Foo>(context),
     child: BarWidget(),
   );
 }

Using Consumer, we can handle this kind of scenario using the optional child argument:

 @override
 Widget build(BuildContext context) {
   return Consumer<Foo>(
     builder: (_, foo, child) => FooWidget(foo: foo, child: child),
     child: BarWidget(),
   );
 }

In that example, BarWidget is built outside of builder. Then, the BarWidget instance is passed to builder as the last parameter.

This means that when builder is called again with new values, new instance of BarWidget will not be recreated. This let Flutter knows that it doesn't have to rebuild BarWidget. Therefore in such configuration, only FooWidget will rebuild if Foo changes.

Note:

The widget Consumer can also be used inside MultiProvider. To do so, it must returns the child passed to builder in the widget tree it creates.

MultiProvider(
  providers: [
    Provider(builder: (_) => Foo()),
    Consumer<Foo>(
      builder: (context, foo, child) =>
        Provider.value(value: foo.bar, child: child),
    )
  ],
);

See also:

Inheritance
Implemented types

Constructors

Consumer5({Key key, @required Widget builder(BuildContext context, A value, B value2, C value3, D value4, E value5, Widget child), Widget child })
Consumes a Provider<T>

Properties

builder Widget Function(BuildContext context, A value, B value2, C value3, D value4, E value5, Widget child)
Build a widget tree based on the value from a Provider<T>. [...]
final
child Widget
The child widget to pass to builder.
final
hashCode → int
The hash code for this object.
read-only, inherited
key Key
Controls how one widget replaces another widget in the tree. [...]
final, inherited
runtimeType → Type
A representation of the runtime type of the object.
read-only, inherited

Methods

build(BuildContext context) Widget
Describes the part of the user interface represented by this widget. [...]
override
cloneWithChild(Widget child) Consumer5<A, B, C, D, E>
Clones the current provider with a new child. [...]
override
createElement() StatelessElement
Creates a StatelessElement to manage this widget's location in the tree. [...]
inherited
debugDescribeChildren() → List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children. [...]
@protected, inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node. [...]
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a non-existent method or property is accessed.
inherited
toDiagnosticsNode({String name, DiagnosticsTreeStyle style }) DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep. [...]
inherited
toString({DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String
Returns a string representation of this object.
inherited
toStringDeep({String prefixLineOne: '', String prefixOtherLines, DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String
Returns a string representation of this node and its descendants. [...]
inherited
toStringShallow({String joiner: ', ', DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String
Returns a one-line detailed description of the object. [...]
inherited
toStringShort() → String
A short, textual description of this widget.
inherited

Operators

operator ==(dynamic other) → bool
The equality operator.
inherited