Flutter Provider:notifyListeners 不更新 AlertDialog 小部件

Flutter Provider: notifyListeners does not update AlertDialog widget

我正在使用 Provider 向我的屏幕和警报对话框提供一些数据。知道 AlertDialog 被挖出小部件树之外,我添加了一个 ChangeNotifierProvider 作为该对话框的包装小部件。但是,UI 并没有改变,即使我确保在提供者状态下更新了这些值。

代码片段:

showTextDialog(BuildContext context) {
  final myModel = Provider.of<ServicesProvider>(context, listen: false);
  return showDialog(
    context: context,
    builder: (_) => ChangeNotifierProvider.value(
      value: myModel,
      child: AlertDialog(
        content: IntrinsicHeight(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Row(
                children: [
                  Radio(
                    value: '0',
                    groupValue: myModel.paymentMethod,
                    onChanged: (value) => myModel.setPaymentMethod('0'),
                    activeColor: ColorResources.PRIMARY_COLOR,
                    toggleable: true,
                  ),
                  SizedBox(width: responsiveWidth(5)),
                  Text("Radio Button 1"),
                ],
              ),
              SizedBox(height: responsiveHeight(10)),
              Row(
                children: [
                  Radio(
                    value: '1',
                    groupValue: myModel.paymentMethod,
                    onChanged: (value) => myModel.setPaymentMethod('1'),
                    activeColor: ColorResources.PRIMARY_COLOR,
                    toggleable: true,
                  ),
                  SizedBox(width: responsiveWidth(5)),
                  Flexible(child: Text("Radio Button 2")),
                ],
              ),
            ],
          ),
        ),
      ),
    ),
  );
}

感谢您的帮助。

你的问题背后的主要思想是你没有订阅 ServicesProvider 的更改。您可以将 Provider.of<ServicesProvider>(context, listen: false); 替换为 context.read<ServicesProvider>();,这是一种使用扩展方法的更简洁的语法。

基于提供商documentation

context.read<T>(), which returns T without listening to it. <...> It's worth noting that context.read<T>() won't make a widget rebuild when the value changes and it cannot be called inside StatelessWidget.build/State.build. On the other hand, it can be freely called outside of these methods.

您已经对 final myModel = Provider.of<ServicesProvider>(context, listen: false); 所做的是您只检索了对 ServicesProvider 的引用。但是,这样您就不会订阅模型内部的更改 - 这正是文档所解释的内容。

要解决此问题,您可以将 AlertDialog 移动到单独的小部件中,例如MyDialog。有一个实际的原因——现在您没有使用相同的上下文,您应该访问 re-provided ServicesProvider 模型,这样更容易理解。现在,通过使用 context.watch<ServicesProvider>()(如果愿意,您也可以使用 Consumer 小部件),您可以订阅模型的更改。因此,当模型内部的 paymentMethod 值发生变化时(您可以通过调用模型上的 setPaymentMethod() 方法来完成),它会触发 UI 重建(notifyListeners()完成它的工作)并且你得到了预期的输出。

您可以找到重新创建和解决的问题 here