Multiple ChangeNotifierProxyProviders to feed updates into ChangeNotifier

909 Views Asked by At

I have three ChangeNotifierProvider providers, let's call them A, B and C.

What I need is for changes in providers A and B to update provider C, but the code below isn't working.

MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (context) => A()),
    ChangeNotifierProvider(create: (context) => B()),
    ChangeNotifierProxyProvider<A, C>(
      create: (context) => C(),
      update: (_, a, c) => c!..updateFromA(a),
    ),
    ChangeNotifierProxyProvider<B, C>(
      create: (context) => C(),
      update: (_, b, c) => c!..updateFromB(b),
    ),
  ]

I think the reason why it doesn't work is because I end up with multiple copies of provider C, but I am not sure how to fix it or what a better alternative implementation would look like.

2

There are 2 best solutions below

0
On BEST ANSWER

After doing some searching, I realized that Flutter provides an elegant out-of-the-box way of solving this problem using ChangeNotifierProxyProvider2.

MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (context) => A()),
    ChangeNotifierProvider(create: (context) => B()),
    ChangeNotifierProxyProvider2<A, B, C>(
      create: (context) => C(),
      update: (_, a, b, c) => c!..updateFromA(a)..updateFromB(b),
    ),
  ]

Flutter also provides ChangeNotifierProxyProvider3 through ChangeNotifierProxyProvider6, but that would, of course, get very verbose and confusing.

1
On

If having more than one instance of C is the problem, then I think you can just use Provider.of<C>(context) to get a single instance.

MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (context) => A()),
    ChangeNotifierProvider(create: (context) => B()),
    ChangeNotifierProvider(create: (context) => C()),
    ChangeNotifierProxyProvider<A, C>(
      create: (context) => Provider.of<C>(context),
      update: (_, a, c) => c!..updateFromA(a),
    ),
    ChangeNotifierProxyProvider<B, C>(
      create: (context) => Provider.of<C>(context),
      update: (_, b, c) => c!..updateFromB(b),
    ),
  ]

Or else, you could apply the singleton pattern to C:

class C {
  static final C _instance = C._();

  factory C() {
    return _instance;
  }

  C._();
}
MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (context) => A()),
    ChangeNotifierProvider(create: (context) => B()),
    ChangeNotifierProxyProvider<A, C>(
      create: (context) => C(),
      update: (_, a, c) => c!..updateFromA(a),
    ),
    ChangeNotifierProxyProvider<B, C>(
      create: (context) => C(),
      update: (_, b, c) => c!..updateFromB(b),
    ),
  ]