提供程序未更新导航屏幕中的值

时间:2021-04-17 14:04:41

标签: flutter dart flutter-provider state-management

我有两个屏幕:

  1. screen A:有一个按钮,当用户点击按钮时,方法addLogFolder被调用并用新值通知所有监听器。然后导航到屏幕 B。
  2. 屏幕 B:这个屏幕有一个容器,它正在监听模型的变化,在屏幕 A 中点击按钮后,它应该将颜色变为红色。

发生了什么:

  • 按钮更改模型中的值 ✓(我已经调试它并且我已经看到模型更改了值)
  • 从屏幕 A 导航到屏幕 B 没有错误 ✓
  • 屏幕 B 的 UI 已更新,因为模型中的值已更改 ✗

屏幕 B 保持不变。当我调试时,我看到它甚至没有收到新值的通知,所以它继续使用旧值。为什么会这样?

代码如下:

构建屏幕 A 的小部件:

return Scaffold(
body: Container(
child: lightTurquoiseElevatedButton(
                   'Proceed', () {
                    Provider.of<LogFoldersModel>(context, listen: false).changeColor();

                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) =>
                            MyHomePage.customConstructor(1), //go to log list
                      ),
                    );
                  }),
),);

构建屏幕 B 的小部件:

return ChangeNotifierProvider(
    create: (context) => LogFoldersModel(),
    child: Scaffold(
      body: Consumer<LogFoldersModel>(
                    builder: (_, logfolder, __) {
                      return Container(
                        height: 47,
                        width: 276,
                        color: logfolder.color, //color should change here
                        child: Text(
                            'Box that has to change color',
                            textAlign: TextAlign.center,
                            style: TextStyle(
                                color: Colors.white,
                                fontSize: 13,
                                fontWeight: FontWeight.w200)),
                      );
                    },
                  ),
    ),
);

LogFoldersModel() 中的 changeColor 方法

class LogFoldersModel extends ChangeNotifier {
  Color color = new Color(0xff707070);

  changeColor() {
    color = Color(0xff664411);
    notifyListeners();
  }
}

注意:当按钮在屏幕 B 中时它工作正常,但现在我想更新另一个屏幕中的值然后导航到屏幕 B,它不起作用。所以我认为问题可能是我在导航中做错了..?

1 个答案:

答案 0 :(得分:1)

我认为您的 ChangeNotifierProvider 应该将您的 MaterialApp 小部件包装在 main.dart 中,而不应该在屏幕 B 中包装任何东西。

这将确保您的所有路由/页面都可以访问 Provider 及其持有的状态对象/值。

我解释一下Provider scope in depth in this answer

如果您有一个 ChangeNotifierProvider 包裹 MaterialApp 和屏幕 B,那么屏幕 B 中的一个在屏幕 B 内部时会从 MaterialApp 遮蔽提供者. 因此,您不会从屏幕 A → 屏幕 B 共享状态。屏幕 B 在其自己的 Provider 范围内。