我们什么时候在 flutter 中初始化一个提供者?

When do we initialise a provider in flutter?

提问人:Clément 提问时间:9/23/2022 更新时间:9/24/2022 访问量:630

问:

我刚刚到达一个 Web 应用程序的 flutter 项目,所有开发人员在使用 flutter provider 进行状态管理时都遇到了问题。

问题
是什么 当您到达屏幕时,通过调用提供程序的函数来初始化相应提供程序的变量。此函数调用 api,并在提供程序中设置变量。
问题:此函数在小部件的构建部分中调用。每次调整窗口大小时,都会重新生成小组件,并再次调用该函数。

我们想要
什么 我们希望在页面第一次显示时调用一个 api,用结果设置变量,并且在重新构建 widget 时不再调用 api。

什么解决方案?

  1. 我们使用第一个屏幕的推送转到第二个屏幕。此时,我们可以调用提供程序的函数,在第二个屏幕之前初始化提供程序。 → 但是在第二页上刷新将清除提供程序变量,并且不会再次调用用于初始化它们的函数。
  2. 我们调用该函数来初始化第二个屏幕的构造函数中的提供程序。这是一个好的模式吗?

感谢您对我使用 flutter :) 的新体验提供的帮助

Flutter 初始化 状态 刷新 提供程序

评论

0赞 Jigar Patel 9/23/2022
在解决方案 1 中,为什么“第二页上的刷新将清除提供程序变量”
0赞 Clément 9/23/2022
当你在 Web Flutter 应用程序中刷新浏览器时,所有状态都会丢失(就像这篇文章一样)。你没有这种行为吗?

答:

0赞 Leonardo Rosa 9/23/2022 #1

据我了解,您可以在进入第二个屏幕之前使用并调用 API 来包装您的应用程序。MultiProvider

评论

0赞 Clément 9/23/2022
是的,它对应于我的解决方案 1,但是刷新浏览器中的第二个屏幕将清除状态,并且我们不会在第一个屏幕上再次初始化提供程序。
1赞 Justin 9/24/2022 #2

我认为你在这里混合了几个不同的问题:

  1. 如何正确初始化提供程序
  2. 如何在初始化时调用方法(仅一次)

对于第一个问题:

在您的文件中,您想执行如下操作:main.dart

@override
Widget build(BuildContext context) {
  return MultiProvider(
    providers: [
      ChangeNotifierProvider(create: (context) => SomeProvider()),
      ChangeNotifierProvider(create: (context) => AnotherProvider()),
    ],
    child: YourRootWidget();
  );
}

然后,在小部件(可能代表应用中的“屏幕”)中,您需要执行如下操作来使用来自该提供程序的状态更改:

@override
Widget build(BuildContext context) {
  return Container(
    child: Consumer<SomeProvider>(
      builder: (context, provider, child) {
        return Text(provider.someState);
      }
    ),
  )
}

你需要做这样的事情来访问提供程序以改变状态:

@override
Widget build(BuildContext context) {
  SomeProvider someProvider = Provider.of<SomeProvider>(context, listen: false);
  return Container(
    child: TextButton(
      child: Text('Tap me'),
      onPressed: () async {
        await someProvider.mutateSomeState();
      }
    ),
  )
}

关于第二个问题...您可以(我认为)只需在小部件上使用该方法即可仅进行 1 次调用。所以。。。initState()

@override
void initState() {
  super.initState();
  AnotherProvider anotherProvider = Provider.of<AnotherProvider>(context, listen: false);
  Future.microtask(() {
    anotherProvider.doSomethingElse();
  });
}

如果我不这样做,我很抱歉。这反映了我的实现并且工作正常/良好。

这里需要注意的是,我认为 RiverPod 可能是您真正想去的地方(它可能更容易使用并且具有有用的其他功能等),但我还没有迁移到 RiverPod,也没有完全弄清楚。

无论如何。。。祝你好运!

评论

0赞 Clément 9/24/2022
这正是我一直在寻找的回应!谢谢!我想避免只为 initState() 使用一个完整的状态小部件,但它可能是最好的解决方案。
0赞 Justin 9/24/2022
也许将提供程序作为构造函数参数传递给小部件?这样你就不需要了.initState()