Search code examples
flutterdependenciesrepopubspec.yaml

Why do I get this error when Importing a flutter app repo as a dependency?


I am using flutter with nfcmanager as part of a project. I want to use the classes from the real world example of an nfcmanager app that I have tested on my machine and works very well inside my code, so I added a fork of the repo as a dependency, and have successfully imported it in.

However there is an issue when I try to run one of the main classes inside the imported code (TagReadPage):

class TagReadPage extends StatelessWidget {
  static Widget withDependency() => ChangeNotifierProvider<TagReadModel>(
        create: (context) => TagReadModel(),
        child: TagReadPage(),
      );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Tag - Read'),
      ),
      body: ListView(
        padding: EdgeInsets.all(2),
        children: [
          FormSection(
            children: [
              FormRow(
                title: Text('Start Session',
                    style: TextStyle(
                        color: Theme.of(context).colorScheme.primary)),
                onTap: () => startSession(
                  context: context,
                  handleTag: Provider.of<TagReadModel>(context, listen: false)
                      .handleTag,
                ),
              ),
            ],
          ),
          // consider: Selector<Tuple<{TAG}, {ADDITIONAL_DATA}>>
          Consumer<TagReadModel>(builder: (context, model, _) {
            final tag = model.tag;
            final additionalData = model.additionalData;
            if (tag != null && additionalData != null)
              return _TagInfo(tag, additionalData);
            return SizedBox.shrink();
          }),
        ],
      ),
    );
  }
}

I can include the other classes being referenced if you need.

When I try to run this class using navigator:

Navigator.push(context,
                        MaterialPageRoute(builder: (context) => TagReadPage()));

I get a useless error message on the terminal, but inside my app this error comes up:

Error: Could not find the correct Provider<TagReadModel> above this Consumer <TagReadModel> Widget

This happens because you used a 'BuildContext' that does not include the provider of your choice. There are a few common scenarios:

You added a new provider in you main.dart and performed a hot reload, to fix perform a hot restart

The provider you are trying to read is in a different route

Providers are scoped so if you insert of provider inside a route, then other routes will not be able to access that provider

You used a BuildContext that is an ancestor of the provider you are trying to read

Make sure than Consumer<TagReadModel> us under your MultiProvider/Provider<TagReadModel>, this usually happens when you are creating a provider and trying to read it immediately

For example, instead of:

Widget build(BuildContext context){
  return Provider<Example>(
    create:(_)=>Example(),
    child: Text(context.watch<Example>().toString()),)}

Consider using builder like so:

Widget build(BuildContext context){
  return Provider<Example>(
    create:(_)=>Example(),
    return Text(context.watch<Example>().toString()

I ran hot restart and same issue. I know that this might be a simple fix but I am still new to flutter so some advice on how to fix this so I can run the class would be great.


Solution

  • The problem you are experiencing is quite common with the Provider package. As you probably already know, Flutter applications are made up of widgets organised in a tree-like structure. The widget tree.

    As a rule of thumb, whenever you use a Consumer, Selector or Provider.of(context) widget, it tries to find the corresponding Provider by traversing the widget tree up to the root. In your case, the Consumer widget will not find a corresponding Provider widget in the widget tree above it until it reaches the top.

    To find their position in the widget tree, widgets use the BuildContext. It is important that the Provider widget is declared above the widget that contains a dependency on the Provider and uses a different BuildContext.

    The author of the sample code has a solution for this problem:

    static Widget withDependency() => ChangeNotifierProvider<TagReadModel>(
            create: (context) => TagReadModel(),
            child: TagReadPage(),
          );
    

    This method wraps the TagReadPage instance in a ChangeNotifierProvider. So if you created it using this static method, the provider should be present in the widget tree. However, you have built the route to this page without using this method. You should change it:

    Navigator.push(context, MaterialPageRoute(builder: (context) => TagReadPage()));
    

    to something like:

    Navigator.push(context, MaterialPageRoute(builder: (context) => TagReadPage.withDependency()));
    

    Hope this works and helps.