How to use multiple Consumers for a single widget in flutter Provider
Asked Answered
T

4

48

I can't wrap my head around using multiple consumers for a single widget with provider? Suppose my widget is CurvedNavigationBar and I have 4 items in that widget. I also have 4 different classes that extend ChangeNotifier and are responsible for each item in CurvedNavigationBar.

How can I listen to those 4 change notifiers in a single widget? I looked at the documentation and could not found such an example.. is this even possible? I found that Consumer has a builder method, so that means you can build a widget only once/and listen to it once.

Should I rather have a single class that extends ChangeNotifier and then update values in that widget and uses only a single Consumer to listen for updated values?

Torgerson answered 23/1, 2020 at 17:26 Comment(0)
A
99

There are some other Consumer widgets. Consumer2, Consumer3, Consumer4 till Consumer6. If you want to listen 4 ChangeNotifier you can use Consumer4

Consumer4(
  builder: (context, changeNotifier1, changeNotifier2, changeNotifier3, changeNotifier4, child) {
    // your widget
  }
)
Ackler answered 24/1, 2020 at 7:33 Comment(7)
Isn't this kind of a weird design? What if you need 7 or more pieces of state?Contempt
@CameronSima To be honest, I have no idea why it is implemented this way. You can see the implementation in github.com/rrousselGit/provider/blob/master/lib/src/…Mechling
I've bursted into laugh at the ConsumN thing, not because they solved my problem.Secession
Excatly... @CameronSima what if i need more provider?Erato
I guess somebody was drunk while coding. Well, it works. Won't complain.Adalard
``` Consumer<ModelBrain>( builder: (context, modelData, child) { ``` how ????Quadragesimal
ah i got it ... i have clicked Consumer and scroll to find out of the core thats the different is Consumer and Consumer2 , Consumer4. oke thankyouQuadragesimal
C
52

Yes you can add up to 6 consumers and will be as following

    Consumer2<AuthProvider, StorageProvider>(
    builder: (context, authProvider, storageProvider, child) {

    }
    )
Cloudcapped answered 6/4, 2020 at 8:49 Comment(0)
T
2

There is another way to get access to your providers: Provider.of<SomeProvider>(context):

Widget build(BuildContext context) {
  final authProvider = Provider.of<AuthProvider>(context);
  final apiProvider = Provider.of<ApiProvider>(context);
  final storageProvider = Provider.of<StorageProvider>(context);

  // Do your usual stuff without wrapping it into Consumer,
  // just pass providers directly to your targets.
  return MyAwesomeWidget(
    authProvider,
    apiProvider,
    storageProvider,
  );
}
Trainee answered 4/10, 2021 at 9:50 Comment(2)
I had same mistake like you (include using Builder Widget), please test it, you'll see it work but it has performance issue, the app will slow down at least 33% for 3 providers. I have to vote it down.Rabi
If you are passing objects fetched from provider into a widget, then you should just get rid of all the parameters and call Provider.of<...> within the widget where it's needed to minimize what is rebuilt.Meistersinger
D
0

For those people who wonder how you would handle the scenario where you would need more than a Consumer6, you could just create your own ConsumerN class. Here is an example of a Consumer7:

/// {@macro provider.consumer}
class Consumer7<A, B, C, D, E, F, G> extends SingleChildStatelessWidget {
  /// {@macro provider.consumer.constructor}
  Consumer7({
    Key? key,
    required this.builder,
    Widget? child,
  }) : super(key: key, child: child);

  /// {@macro provider.consumer.builder}
  final Widget Function(
    BuildContext context,
    A value,
    B value2,
    C value3,
    D value4,
    E value5,
    F value6,
    G value7,
    Widget? child,
  ) builder;

  @override
  Widget buildWithChild(BuildContext context, Widget? child) {
    return builder(
      context,
      Provider.of<A>(context),
      Provider.of<B>(context),
      Provider.of<C>(context),
      Provider.of<D>(context),
      Provider.of<E>(context),
      Provider.of<F>(context),
      Provider.of<G>(context),
      child,
    );
  }
}

But if you really do need more than a Consumer6, then might I suggest that you review your design and see if it can be simplified?

Definiens answered 4/6 at 21:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.