ProviderNotFoundException 在构建 ConsumptionDialog 时被抛出,因为使用了不包含提供者的“BuildContext”
ProviderNotFoundException was thrown building ConsumptionDialog because used `BuildContext` that does not include the provider
我是一名学生,我在学校没有学习移动开发。如果有人能帮助我,我真的很感激。我不知道如何修复错误,我尝试了无数次。
Error: Could not find the correct Provider above this Builder Widget. This happens because you used a 'BuildContext' that does not include the provider of your choice.
导致错误的相关小部件是
消费对话框。此错误涉及 2 个文件。
第一个文件:consumption_dialog.dart
class ConsumptionDialog extends StatefulWidget {
@override
_ConsumptionDialogState createState() => _ConsumptionDialogState();
}
class _ConsumptionDialogState extends State<ConsumptionDialog> {
final _form = GlobalKey<FormState>();
String? _text;
String? _validateText(String? value) {
if (value == null) {
return "2000 ml minimun";
}
final number = int.tryParse(value);
if (number != null && number >= 2000) {
return null;
}
return "2000 ml minimum";
}
@override
Widget build(BuildContext context) {
final bloc = context.watch<WaterBloc>();
return AlertDialog(
title: Text(
"Daily consumption",
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.bold),
),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
content: Form(
key: _form,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Change your daily water consumption goal, in milliliters.",
textAlign: TextAlign.center,
),
SizedBox(height: 12),
TextFormField(
maxLength: 4,
initialValue: bloc.state.recommendedMilliliters.toString(),
keyboardType: TextInputType.number,
onSaved: (value) => _text = value,
validator: _validateText,
autovalidateMode: AutovalidateMode.onUserInteraction,
decoration: InputDecoration(
hintText: "2000 ml",
counterText: "",
),
),
SizedBox(height: 24),
PrimaryButton(
onPressed: () {
if (_form.currentState?.validate() ?? false) {
_form.currentState?.save();
FocusScope.of(context).unfocus();
context.read<WaterBloc>().setRecommendedMilliliters(
int.parse(_text!),
);
Navigator.of(context).pop();
}
},
title: "Confirm",
),
SizedBox(height: 10),
SecondaryButton(
onPressed: () => Navigator.of(context).pop(),
title: "Cancel",
),
],
),
),
);
}
}
内联显示错误:
Widget build(BuildContext context) {
final bloc = context.watch<WaterBloc>();
return AlertDialog(
第二个文件:dialog.dart
import 'package:flutter/material.dart';
import 'package:animations/animations.dart';
import 'package:stayhydratedpal/widgets/confirmation_dialog.dart';
import 'package:stayhydratedpal/widgets/consumption_dialog.dart';
Future<bool> showConfirmationDialog(
BuildContext context, {
required String title,
required String content,
}) async {
final bool confirmed = await showModal(
context: context,
builder: (context) {
return ConfirmationDialog(
title: title,
content: content,
onConfirm: () => Navigator.of(context).pop(true),
onCancel: () => Navigator.of(context).pop(false),
);
},
) ??
false;
return confirmed;
}
Future<void> showConsumptionDialog(BuildContext context) {
return showModal(
context: context,
builder: (context) => ConsumptionDialog(),
);
}
内联显示错误:
Future<void> showConsumptionDialog(BuildContext context) {
return showModal(
context: context,
builder: (context) => ConsumptionDialog(),
);
}
提供程序的工作方式是当您执行 Provider.of<T>(context)
(上下文必须是您注入 T 的小部件的后代)时,它会查找树以找到您使用 [=14= 注入的 T ](可以是 ChangeNotifierProvider 也没关系)。导航器堆栈中的路由也不是彼此的父级
他们是
-> page1
-> page2
没有
-> page1
-> page2
所以这意味着当您使用 Navigator 推送新页面时,Provider 将无法找到您放置在 page1 上的注入提供程序。 showModal 使用 Navigator push 打开一个对话框,所以基本上就像任何其他路线一样,这意味着您的 ConfirmationDialog 没有找到您可能在打开它的页面中注入的 WaterBloc。
解决此问题的一种方法是在 Navigator 上方注入 WaterBloc,MaterialApp 包含根导航器,因此在 Material App 上方注入提供程序。
另一种方法是打开对话框时你可以做
Future<void> showConsumptionDialog(BuildContext context) {
return showModal(
context: context,
builder: (_) => Provider.value(
value: context.read<WaterBloc>(), // this context must be a descendent of the widget where you injected WaterBloc
child: ConsumptionDialog(),
),
);
}
一个小技巧,我建议你稍微学习一下 Inherited Widgets,如果你学得好,你可以很容易地使用 Provider,因为 Provider 只是 InheritedWidget 的包装器
我是一名学生,我在学校没有学习移动开发。如果有人能帮助我,我真的很感激。我不知道如何修复错误,我尝试了无数次。
Error: Could not find the correct Provider above this Builder Widget. This happens because you used a 'BuildContext' that does not include the provider of your choice.
导致错误的相关小部件是 消费对话框。此错误涉及 2 个文件。
第一个文件:consumption_dialog.dart
class ConsumptionDialog extends StatefulWidget {
@override
_ConsumptionDialogState createState() => _ConsumptionDialogState();
}
class _ConsumptionDialogState extends State<ConsumptionDialog> {
final _form = GlobalKey<FormState>();
String? _text;
String? _validateText(String? value) {
if (value == null) {
return "2000 ml minimun";
}
final number = int.tryParse(value);
if (number != null && number >= 2000) {
return null;
}
return "2000 ml minimum";
}
@override
Widget build(BuildContext context) {
final bloc = context.watch<WaterBloc>();
return AlertDialog(
title: Text(
"Daily consumption",
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.bold),
),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
content: Form(
key: _form,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Change your daily water consumption goal, in milliliters.",
textAlign: TextAlign.center,
),
SizedBox(height: 12),
TextFormField(
maxLength: 4,
initialValue: bloc.state.recommendedMilliliters.toString(),
keyboardType: TextInputType.number,
onSaved: (value) => _text = value,
validator: _validateText,
autovalidateMode: AutovalidateMode.onUserInteraction,
decoration: InputDecoration(
hintText: "2000 ml",
counterText: "",
),
),
SizedBox(height: 24),
PrimaryButton(
onPressed: () {
if (_form.currentState?.validate() ?? false) {
_form.currentState?.save();
FocusScope.of(context).unfocus();
context.read<WaterBloc>().setRecommendedMilliliters(
int.parse(_text!),
);
Navigator.of(context).pop();
}
},
title: "Confirm",
),
SizedBox(height: 10),
SecondaryButton(
onPressed: () => Navigator.of(context).pop(),
title: "Cancel",
),
],
),
),
);
}
}
内联显示错误:
Widget build(BuildContext context) {
final bloc = context.watch<WaterBloc>();
return AlertDialog(
第二个文件:dialog.dart
import 'package:flutter/material.dart';
import 'package:animations/animations.dart';
import 'package:stayhydratedpal/widgets/confirmation_dialog.dart';
import 'package:stayhydratedpal/widgets/consumption_dialog.dart';
Future<bool> showConfirmationDialog(
BuildContext context, {
required String title,
required String content,
}) async {
final bool confirmed = await showModal(
context: context,
builder: (context) {
return ConfirmationDialog(
title: title,
content: content,
onConfirm: () => Navigator.of(context).pop(true),
onCancel: () => Navigator.of(context).pop(false),
);
},
) ??
false;
return confirmed;
}
Future<void> showConsumptionDialog(BuildContext context) {
return showModal(
context: context,
builder: (context) => ConsumptionDialog(),
);
}
内联显示错误:
Future<void> showConsumptionDialog(BuildContext context) {
return showModal(
context: context,
builder: (context) => ConsumptionDialog(),
);
}
提供程序的工作方式是当您执行 Provider.of<T>(context)
(上下文必须是您注入 T 的小部件的后代)时,它会查找树以找到您使用 [=14= 注入的 T ](可以是 ChangeNotifierProvider 也没关系)。导航器堆栈中的路由也不是彼此的父级
他们是
-> page1
-> page2
没有
-> page1
-> page2
所以这意味着当您使用 Navigator 推送新页面时,Provider 将无法找到您放置在 page1 上的注入提供程序。 showModal 使用 Navigator push 打开一个对话框,所以基本上就像任何其他路线一样,这意味着您的 ConfirmationDialog 没有找到您可能在打开它的页面中注入的 WaterBloc。
解决此问题的一种方法是在 Navigator 上方注入 WaterBloc,MaterialApp 包含根导航器,因此在 Material App 上方注入提供程序。
另一种方法是打开对话框时你可以做
Future<void> showConsumptionDialog(BuildContext context) {
return showModal(
context: context,
builder: (_) => Provider.value(
value: context.read<WaterBloc>(), // this context must be a descendent of the widget where you injected WaterBloc
child: ConsumptionDialog(),
),
);
}
一个小技巧,我建议你稍微学习一下 Inherited Widgets,如果你学得好,你可以很容易地使用 Provider,因为 Provider 只是 InheritedWidget 的包装器