0

I'm working with the provider package for Flutter. What I want to accomplish is to have a simple provider just for one view or page. So I tried the following in my widget:

Widget build(BuildContext context) {
    return ChangeNotifierProvider<MyModel>(
      create: (_) => MyModel(),
      child: Scaffold(
        appBar: AppBar(
          title: Text(
            'Screen 1',
          ),
        ),
        body: _buildBody(),
      ),
    );
  }

but when I try to access the provider using a Provider.of<MyModel>(context, listen: false).value in my _buildBody() method I get the error:

Could not find the correct Provider above this MyPageWidget

When I move the declaration of the provider to where I declare my App above this Widget it works. Unfortunately this makes the provider public for all of my views to access which is not what I want. How can I make a provider that just can be accessed within that one view or widget. Thanks for any help.


Note: I tried this answer but I'm still getting the same result.

Edit: I could use a Consumer at the top of my widget tree, but doesn't that cause the page to rebuild too much if my whole widget tree is in the Consumer. Further, what if I need to use Provider.of(...)?

Gabe
  • 5,643
  • 3
  • 26
  • 54

2 Answers2

2

Try wrapping the scaffold with consumer

Widget build(BuildContext context) {
return ChangeNotifierProvider<MyModel>(
  create: (_) => MyModel(),
  child: Consumer(
    builder: (context, MyModel model, _) => Scaffold(
      appBar: AppBar(
        title: Text(
          'Screen 1',
        ),
      ),
      body: _buildBody(),
    ),
  ));
}

Now u can access my model directly by passing it through the method

GJJ2019
  • 4,624
  • 3
  • 12
  • 22
  • This seems like a round-a-bout way of accomplishing this because now the whole widget tree gets rebuilt every time there is a change and I have to pass `model` into every function. Is what I'm trying to accomplish in provider an anti-pattern, or is there a better way to do this? – Gabe Feb 23 '20 at 15:18
  • Does the whole widget tree get rebuilt every time `notifyListeners()` is called when everything is wrapped by the `Consumer`? – Gabe Feb 26 '20 at 16:01
  • but if i want to call some function from a provider in initState() or didChangedependencies() , this can't be possible using the above code. – Avnish Nishad Jun 13 '21 at 18:03
2

I finally figured out a solution to this that doesn't require rebuilding the whole widget tree when a change happens like @GJJ2019 answer. When I declare the route, for example:

'/': (context) => MyScreen();

I wrap MyScreen with the ChangeNotifierProvider for example:

'/': (context) => ChangeNotifierProvider<MyModel>(
  create: (_) => MyModel(),
  child: MyScreen()),

So instead of declaring the provider in the widget/screen that it was being used, declare the provider where you declare the route.

Gabe
  • 5,643
  • 3
  • 26
  • 54
  • So, I understand, we should put Providers at the top of the app, it means placing them at Main.dart right? – Cuong Vo Apr 23 '21 at 02:53