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。
我正在使用 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。