0

I'm trying to understand multiproviders in Flutter. In my App, one Provider need to change based on a value from an other Provider.

AuthProvider gets initiated higher up in the widget tree on build. Works like a charm with automatic sign in if possible...

In a lower placed widget, I try to initiate two other Providers. One, WhatEver, is not depended on other data and gets initiated on build like it is supposed to using ChangeNotifierProvider.

ProductList however is depended on AuthProvider. If log in status is changed, the ProducList should update accordingly.

In my attempts, I've found out, ie found on SO, that ChangeNotifierProxyProvider is the right way to go. But when I run the App, it seems like the 'create'-part of ChangeNotifierProxyProvider is not initiated when the widget gets build. It seems like the ProductList provider is not initiated until it's read or written to.

What have I misunderstood using MultiProviders and ChangeNotifierProxyProvider?

return MultiProvider(
        providers: [              
          ChangeNotifierProvider<WhatEver>(create: (context) => WhatEver()),
          ChangeNotifierProxyProvider<AuthProvider, ProductList>(
            create: (_) => ProductList(Provider.of<AuthProvider>(context, listen: false)),
            update: (_, auth, productList) => productList..reloadList(auth)
          ),
        ],

The ProductList looks like this:

final AuthProvider _authProvider;

static const String _TAG = "Shop - product_list.dart : ";

ProductList(this._authProvider) {
    print(_TAG + "ProductList Provider initiated");
    reloadList(this._authProvider);
}

void reloadList(AuthProvider authProvider) {
    print(_TAG + "ProductList reload started");
    if (authProvider.user==null) {
        print(_TAG + "ProductList: _authProvider == null");
        _loadBuiltInList();
    } else {
        print(_TAG + "ProductList: user = " + authProvider.user.displayName);
        _loadFirestoreList();
    }
}
user1086500
  • 380
  • 5
  • 20
  • 1
    Could it be `lazy` ? [See this answer](https://stackoverflow.com/questions/60777133/flutter-multiprovider-classes-constructors-issue/63256452#63256452) – Eduardo Mar 27 '21 at 13:34
  • Lady sees to be correct. Opened up for other problems though – user1086500 Mar 27 '21 at 16:58

2 Answers2

0

Could be because you're not using the context passed in the create call when you resolve the AuthProvider. You're capturing the context in scope for this whole statement - and later resolving the AuthProvider from that.

Try making use of the context parameter as per:

return MultiProvider(
        providers: [              
          ChangeNotifierProvider<WhatEver>(create: (context) => WhatEver()),
          ChangeNotifierProxyProvider<AuthProvider, ProductList>(
            create: (ctx) => ProductList(Provider.of<AuthProvider>(ctx, listen: false)),
            update: (_, auth, productList) => productList..reloadList(auth)
          ),
        ],

There's a pattern when creating CN dependency chains of asynchronously initializable objects ... but it's outside the scope of this question.

-1

I have code that does this:

ChangeNotifierProxyProvider<AuthService, ProfileService>(
  create: (ctx) => ProfileService(),
  update: (ctx, authService, profileService) =>
      profileService..updateAuth(authService),
),

My ProfileService() does not rely on AuthService being available when it is constructed. The code works fine :)

The ChangeNotifierProxyProvider documentation explicitly describes this approach:

Notice how MyChangeNotifier doesn't receive MyModel in its constructor anymore. It is now passed through a custom setter/method instead.

Patrick O'Hara
  • 1,999
  • 1
  • 14
  • 18
  • Eduardos link to an other answer was correct. ChangeNotifierProxyProvider is lazy. If lazy is set to false, it gets initiated on build. – user1086500 Mar 27 '21 at 23:47