我是一名學生,我在學校不學習移動開發。如果有人能幫助我,我真的很感激。我不知道如何修復錯誤,我嘗試了無數次。
錯誤:無法在此構建器小部件上方找到正確的提供程式。發生這種情況是因為您使用了不包含您選擇的提供程式的“BuildContext”。
相關的導致錯誤的小部件是 ConsumptionDialog。此錯誤涉及 2 個檔案。
第一個檔案:consume_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(),
);
}
uj5u.com熱心網友回復:
提供程式的作業方式是當您這樣做時Provider.of<T>(context)(背景關系必須是您注入 T 的小部件的后代),它會查找樹以找到您使用的 T 注入Provider(create: (_)=> 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 的包裝器
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/342549.html
下一篇:Dart中的穩定串列集差
