provider icon indicating copy to clipboard operation
provider copied to clipboard

MultiProvider does not support above 168 providers

Open tuhinansu-gourav opened this issue 2 years ago • 30 comments

Describe the bug If we add more than 168 providers to Multi Provider then on iOS simulator it does not work.(stack overflow error) On real device and on Android it works fine

To Reproduce

Just add more than 168 providers and try to run on iOS simulator. Also please use Navigator.

Expected behavior It should support more than 168 providers. If don't use multi-provider, and add more than 168 providers then it works

tuhinansu-gourav avatar Dec 03 '21 06:12 tuhinansu-gourav

It's not really a bug, rather it's a limitation of the widget tree, which depends on your device

Optimisations are possible, but removing the limit is difficult

rrousselGit avatar Dec 05 '21 12:12 rrousselGit

@rrousselGit Can you please locate me the place where this limitation code is present ?

I would like to remove this limitation for my project.

tuhinansu-gourav avatar Dec 06 '21 03:12 tuhinansu-gourav

There's no particular place.

rrousselGit avatar Dec 06 '21 08:12 rrousselGit

But then why is the problem only happening in debug mode in iOS simulator ? I have tried in iPhone 13 Pro Max, iOS 15

This is not happening in android !!

tuhinansu-gourav avatar Dec 07 '21 03:12 tuhinansu-gourav

I found similar issues faced by others. It maybe a limitation of flutter https://github.com/flutter/flutter/issues/85026 https://github.com/flutter/flutter/issues/73734

But I think this should be fixed some where, either here or by flutter.

tuhinansu-gourav avatar Dec 07 '21 05:12 tuhinansu-gourav

That "limit" is built directly in the device. It's not Flutter or Provider that decides to throw a StackOverflow error, but the device that tells that it reached its stack limit

rrousselGit avatar Dec 07 '21 10:12 rrousselGit

But shouldn't the framework and packages be built depending upon the device configuration rather than the other way around ?

tuhinansu-gourav avatar Dec 07 '21 14:12 tuhinansu-gourav

The problem with provider package is that it increases this hierarchy without considering this limitation.

tuhinansu-gourav avatar Dec 07 '21 14:12 tuhinansu-gourav

What exactly do you expect provider to do here?

rrousselGit avatar Dec 11 '21 17:12 rrousselGit

I expect that if flutter is not able to support deep hierarchy widget tree, then provider shouldn't keep increasing the widget tree. Maybe find a better way to do what it is doing but not increasing the hierarchy. e.g. redux in react

tuhinansu-gourav avatar Dec 11 '21 18:12 tuhinansu-gourav

Proivders are widgets. They'll always increase the hierarchy

They would in Redux too. It's just that in Redux, you define a single StoreProvider instead of 168 providers. You could have one large provider if you wanted to

rrousselGit avatar Dec 11 '21 18:12 rrousselGit

https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html Inherited widgets don't increase widget tree.

BTW, how to have one large provider ? Can you please give me an example ?

tuhinansu-gourav avatar Dec 11 '21 18:12 tuhinansu-gourav

Inheritedwidget are widgets, therefore increase the size of the widget tree

BTW, how to have one large provider ? Can you please give me an example ?

Regroup multiple class into a larger one.

Redux is one monolithic object

rrousselGit avatar Dec 11 '21 18:12 rrousselGit

you can have "unlimited" provider using this approach:

 MultiProvider(
      providers: [
            ChangeNotifierProvider(create: (_) => AppProvider()),
      ],
      child: MaterialApp(...),
 )

then

 class AppProvider extends ChangeNotifier {

      late HomeProvider homeProvider;
      late SecondProvider secondProvider;

      AppProvider() {
           homeProvider = HomeProvider();
           secondProvider = SecondProvider();
      }
 
 }

in home page you can call

HomeProvider get provider => context.read<AppProvider>().homeProvider;

haven't test for hundreds provider yet, but what do you think? @rrousselGit

nashihu avatar Jun 29 '22 02:06 nashihu

is this happen for real devices in release mode ?

nikhith265 avatar Jan 13 '23 04:01 nikhith265

Getting StackOverflowError after upgrading to Flutter 3.7 only on iOS. We also use MultiProvider with many global providers. @rrousselGit what is your advice to solve it? Scoping providers? Stop using MultiProvider and using lots of individual providers?

@tuhinansu-gourav said that changing to many individual providers worked.

brunovsiqueira avatar Feb 14 '23 00:02 brunovsiqueira

You can stop using MultiProvider yes. That should raise the limit quite a bit, at the cost of readability.

rrousselGit avatar Feb 14 '23 00:02 rrousselGit

@rrousselGit So, since providers nests each other, the only solution that escalates is not to have dozens of providers above the same widget tree. Am I right?

brunovsiqueira avatar Feb 14 '23 00:02 brunovsiqueira

You can stop using MultiProvider yes. That should raise the limit quite a bit, at the cost of readability.

I don't see why it would raise the limit. Wouldn't the providers be nested anyway?

brunovsiqueira avatar Feb 14 '23 00:02 brunovsiqueira

MultiProvider works by adding extra widgets under the hood

Not using it means those extra widgets are no-longer here, which gives you a few extra slots for providers

rrousselGit avatar Feb 14 '23 08:02 rrousselGit

@rrousselGit if I migrate to Riverpod (I haven't read the docs yet), would it solve the problem of the widget tree? Or Riverpod does have the same InheritedWidget problem for multiple providers?

brunovsiqueira avatar Feb 14 '23 14:02 brunovsiqueira

It would solve the problem yes.

Riverpod only uses a single widget for storing providers (ProviderScope). As opposed to with Provider where every provider counts for 2-3 widgets

rrousselGit avatar Feb 14 '23 15:02 rrousselGit

@rrousselGit (I can contact you in another way if it is not scope of this issue). We use ChangeNotifier for almost everything regarding state management in our project. I know in RiverPod you wanted to push immutability, and I think that's pretty nice. I was just wondering if sometime in the future you are thinking about removing ChangeNotifier from Provider?

brunovsiqueira avatar Feb 14 '23 21:02 brunovsiqueira

Why would I do that?

rrousselGit avatar Feb 15 '23 09:02 rrousselGit

@rrousselGit , do you think keeping the MultiProvider but using lazy: true on the ChangeNotifierProviders would help with this case?

IsaAmante avatar Mar 14 '23 18:03 IsaAmante

No because lazy or not has no impact on the depth of the tree

rrousselGit avatar Mar 14 '23 22:03 rrousselGit

The issue is known by flutter. There is a fix That permits to "reset" the tree depth, avoiding stackoverflow => https://github.com/flutter/flutter/issues/85026#issuecomment-885428067

This could be a good fix for provider, wrapping the child in MultiProvider in a LayoutBuilder

Thelm76 avatar Apr 28 '23 15:04 Thelm76

The problem is, that would make MultiProvider insert RenderObjects – which is UI related. Providers are currently UI-independent at the moment (no RenderObject involved).

But you can do that on your own. MultiProvider supports inserting a Consumer too:

MultiProvider(
  providers: [
    Provider(...),
    Consumer<Null>(builder: (ctx, _, child) {
       return LayoutBuilder(builder: (ctx, _) => child);
     }),
     Provider(...),
  ],
)

rrousselGit avatar Apr 28 '23 15:04 rrousselGit

The problem is, that would make MultiProvider insert RenderObjects – which is UI related. Providers are currently UI-independent at the moment (no RenderObject involved).

But you can do that on your own. MultiProvider supports inserting a Consumer too:

MultiProvider(
  providers: [
    Provider(...),
    Consumer<Null>(builder: (ctx, _, child) {
       return LayoutBuilder(builder: (ctx, _) => child);
     }),
     Provider(...),
  ],
)

The following error appears while doing this.

The following ProviderNotFoundException was thrown building Consumer<Null>(dirty): Error: Could not find the correct Provider<Null> above this Consumer<Null> Widget

nikhith265 avatar May 02 '23 07:05 nikhith265

I think earlier @rrousselGit was just giving an example. The new error that you are getting is that, a consumer can only access providers that are above it in widget tree. You can check it in widget inspector.

tuhinansu-gourav avatar May 04 '23 09:05 tuhinansu-gourav