У меня есть экран, который использует значения из ChangeNotifierProvider для отображения содержимого экрана. Как и ожидалось, при изменении этих значений запускается метод построения экрана и обновляется содержимое экрана.
Я бы хотел, чтобы при изменении одного из этих значений с false на true на этом экране открывался диалог.
Я понял, что единственный способ открыть этот диалог — запустить его из метода сборки, когда значение изменилось и вызывается новая сборка.
Я знаю, что showDialog — это асинхронный метод, в то время как сборка синхронизируется, и это антипаттерн для управления этими побочными эффектами изнутри метода сборки. Я не могу знать, когда будет вызван метод сборки, и это может привести к тому, что каждый раз при вызове сборки будет открываться несколько диалоговых окон.
Итак, пока я могу открыть диалог только из метода сборки и использовать логический флаг в памяти, чтобы контролировать, открыт ли диалог или нет. Как это:
class MyScreen extends StatefulWidget {
const MyScreen();
@override
State<StatefulWidget> createState() => _MyScreenState();
}
class _MyScreenState extends State<MyScreen> {
late final myModel = Provider.of<MyModel?>(context);
bool _isDialogShowing = false;
@override
void initState() {
super.initState();
...
}
void _showMyDialog(BuildContext ctx) {
showDialog(
context: ctx,
barrierDismissible: false,
builder: (context) => AlertDialog(
content: const Text("Hello I am a dialog"),
),
).then((val) {
// The dialog has been closed
_isDialogShowing = true;
});
}
@override
Widget build(BuildContext context) {
// Open dialog if value from `ChangeNotifierProvider` has changed
if (myModel?.hasToShowDialog == true && _isDialogShowing == false) {
_isDialogShowing = true;
Future.delayed(
Duration.zero,
() {
_showMyDialog(context);
},
);
}
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
.....
],
),
],
);
}
}
Знаете ли вы, как правильно вызвать событие открытия диалогового окна при изменении значения в ChangeNotifierProvider? Большое тебе спасибо!!!





Что вы можете сделать, так это добавить слушателя в свой ChangeNotifier:
late final myModel = Provider.of<MyModel?>(context);
bool _isDialogShowing = false;
@override
void initState() {
super.initState();
myModel.addListener(_showDialog);
}
@override
void dipose() {
myModel.removeListener(_showDialog);
super.dispose();
}
Future<void> _showDialog() async {
if (_isDialogShowing || !mounted) return;
// `hasToShowDialog` could be a getter and not a variable.
if (myModel?.hasToShowDialog != true) return;
_isDialogShowing = true;
await showDialog(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
content: const Text("Hello I am a dialog"),
),
);
_isDialogShowing = false;
}
Я не знаю, как выглядит ваш MyModel, поэтому трудно понять, что еще вы могли бы найти. hasToShowDialog может быть геттером, а не переменной, как вы предложили в своем вопросе.