Flutter Provider:notifyListeners 不更新 AlertDialog 小部件

MU'*_*med 1 dart flutter flutter-provider

我用来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")),
                ],
              ),
            ],
          ),
        ),
      ),
    ),
  );
}
Run Code Online (Sandbox Code Playgroud)

感谢您的帮助。

mko*_*lys 6

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

基于提供商文档

context.read<T>(),返回 T 而不监听它。<...> 值得注意的是,当值发生变化时, context.read<T>() 不会使小部件重建,并且不能在 StatelessWidget.build/State.build 中调用。另一方面,它可以在这些方法之外自由调用。

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

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

您可以在此处找到重新创建和解决的问题。