flutter - 关于 flutter 的 provider 中发生的错误

标签 flutter state provider

我正在了解 flutter 的提供者,但我遇到了一个错误。

以下代码有效。

[code1]
class Model extends ChangeNotifier {
  void save() {
    print('save');
  }
}
class Main extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => Model(),
      child: Scaffold(
        appBar: AppBar(
          title: Text('test'),
        ),
        body: NewWidget(),
      ),
    );
  }
}

class NewWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      child: Text(
        "test",
      ),
      onPressed: () {
        context.read<Model>().save();
      },
    );
  }
}

但是下面的代码不起作用。
[code2]
class Model extends ChangeNotifier {
  void save() {
    print('save');
  }
}

class Main extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => Model(),
      child: Scaffold(
        appBar: AppBar(
          title: Text('test'),
        ),
        body: RaisedButton(
          child: Text(
            "test",
          ),
          onPressed: () {
            context.read<Model>().save();
          },
        ),
      ),
    );
  }
}

使用此代码,按下按钮时会输出以下错误。
Error: Could not find the correct Provider<Model> above this Main Widget

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

- 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 that Main is under your MultiProvider/Provider<Model>.
  This usually happen when you are creating a provider and trying to read it immediatly.

  For example, instead of:

我不分离小部件,我想编写一个像 code2 这样的小部件。
请让我知道是否有任何好的方法。

谢谢!

最佳答案

在您的第一个示例中,NewWidget是用新的 BuildContext 构建的,已经可以访问它的祖先,所以这个小部件可以看到你在那里创建的提供者:context.read<Model>() .

但是,在您的第二个示例中,您将在同一个 Widget Main 中创建和使用您的提供程序。所以一切都一样BuildContext ,当你运行 context.read<Model>() flutter 将尝试在您的 Widget 树中查找 Model ,但它不会找到它,因为您刚刚创建了它。这是您可以使用 Builder 的场景。小部件:

class Main extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => Model(),
      child: Scaffold(
        appBar: AppBar(
          title: Text('test'),
        ),
        body: Builder(
          // Here the magic happens
          // this builder function will generate a new BuilContext for you
          builder: (BuildContext newContext){
            return RaisedButton(
              child: Text(
                "test",
              ),
              onPressed: () {
                 newContext.read<Model>().save();
              },
            );
          }
        ),
      ),
    );
  }
}

通过使用 Builder小部件,您可以新建BuildContext可用于检索有关您刚刚创建的提供程序的信息,这是因为您的 Builder 小部件是在您的 ChangeNotifierProvider 之后构建的,并且它是它的子项,因此它可以轻松查找并在其父项上找到此信息。

还要注意错误告诉您的内容,flutter 编译器在处理此类问题时非常聪明:

Make sure that Main is under your MultiProvider/Provider. This usually happen when you are creating a provider and trying to read it immediatly.



这些行准确地告诉您我之前解释过的内容。

关于flutter - 关于 flutter 的 provider 中发生的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62418382/

相关文章:

dart - 如何在页面加载时打开脚手架的抽屉?

ios - 如何从 native ios View 弹出回 flutter View ?

flutter - 我想要一个在关闭后自动打开的AlertDialog

ios - iOS 中的自定义按钮和状态

web-applications - 在什么情况下,有状态的网络比无状态的更好?

.net - DB2 .NET提供者建议

flutter - 在 Flutter 中使用半透明灰色填充渲染的 RaisedButton

state - 自循环上的两个输入,确定性或非确定性状态机?

Flutter Draggable - 如何将 Draggable 重置到起始位置?

linq - 创建 Linq->HQL 提供程序