flutter - 错误:找不到正确的提供者在这个 Builder Widget 上方
问题描述
我正在开发一个小型的待办事项列表应用程序,而且我是这个Provider
包的新手。我收到此错误:
错误:在此构建器小部件上方找不到正确的提供程序。发生这种情况是因为您使用了不包括您选择的提供者的“BuildContext”。
When the exception was thrown, this was the stack:
#0 Provider._inheritedElementOf (package:provider/src/provider.dart:332:7)
#1 Provider.of (package:provider/src/provider.dart:284:30)
#2 HomePage.build.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:mytodolist/main.dart:57:36)
#3 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:994:20)
#4 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
...
Handler: "onTap"
Recognizer: TapGestureRecognizer#9540a
debugOwner: GestureDetector
state: possible
won arena
finalPosition: Offset(308.6, 425.5)
finalLocalPosition: Offset(34.8, 20.3)
button: 1
sent tap down
这是我的main.dart
:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:mytodolist/TodoModel.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.blue,
accentColor: Colors.orange,
),
home: ChangeNotifierProvider(
create: (context) => TodoModel(),
child: HomePage(),
)
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("mytodos"),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)),
title: Text("Add Todolist"),
content: TextField(
onChanged: (String value) {
Provider.of<TodoModel>(context, listen: false)
.addTitle(value);
},
),
actions: <Widget>[
TextButton(
onPressed: () {
Provider.of<TodoModel>(context, listen: false)
.createTodos();
Navigator.of(context).pop();
},
child: Text("Add"))
],
);
});
},
child: Icon(
Icons.add,
color: Colors.white,
),
),
body: StreamBuilder(
stream: FirebaseFirestore.instance.collection("MyTodos").snapshots(),
builder: (context, snapshots) {
if (snapshots.data == null) return CircularProgressIndicator();
return Consumer<TodoModel>(builder: (context, todo, child) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshots.data.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot documentSnapshot =
snapshots.data.docs[index];
return Dismissible(
onDismissed: (direction) {
Provider.of<TodoModel>(context, listen: false)
.deleteTodos(documentSnapshot["todoTitle"]);
},
key: Key(documentSnapshot["todoTitle"]),
child: Card(
elevation: 4,
margin: EdgeInsets.all(8),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)),
child: ListTile(
title: Text(documentSnapshot["todoTitle"]),
trailing: IconButton(
icon: Icon(Icons.delete),
color: Colors.red,
onPressed: () {
/*setState(() {
todos.removeAt(index);
});*/
Provider.of<TodoModel>(context, listen: false)
.deleteTodos(documentSnapshot["todoTitle"]);
},
),
),
));
});
});
}),
);
}
}
这是我的 TodoModel.dart:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
class TodoModel extends ChangeNotifier {
// List todos = [];
String todoTitle = "";
createTodos() {
DocumentReference documentReference =
FirebaseFirestore.instance.collection("MyTodos").doc(todoTitle);
// Map
Map<String, String> todos = {"todoTitle": todoTitle};
documentReference.set(todos).whenComplete(() =>
print("$todoTitle created"));
}
deleteTodos(item) {
DocumentReference documentReference =
FirebaseFirestore.instance.collection("MyTodos").doc(item);
documentReference.delete().whenComplete(() => print("$item deleted"));
}
addTitle(String title) {
todoTitle = title;
}
}
在main.dart
中,我相信我已经举起了ChangeNotifierProvider
足够高的高度,可以让它的孩子、HomePage
班级、使用Provider.of<TodoModel>(content).xxx
. 为什么在Builder Widget上面还是会弹出找不到正确Provider的错误?
解决方案
请使用HomePage
' 上下文而不是showDialog
' 构建器。
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) { // <<<<<<< USE THIS CONTEXT
return Scaffold(
appBar: AppBar(
title: Text("mytodos"),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext dialogContext) { // <<<<<<< DO NOT USE THIS CONTEXT
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)),
title: Text("Add Todolist"),
content: TextField(
onChanged: (String value) {
// <<<<<<< context = HomePage's BuildContext
// <<<<<<< context != dialogContext
Provider.of<TodoModel>(context, listen: false)
.addTitle(value);
},
),
actions: <Widget>[
TextButton(
onPressed: () {
// <<<<<<< context = HomePage's BuildContext
// <<<<<<< context != dialogContext
Provider.of<TodoModel>(context, listen: false)
.createTodos();
Navigator.of(context).pop();
},
child: Text("Add"))
],
);
});
},
推荐阅读
- javascript - 从元素接收文本
- dart - 如何在 Dart 中将二进制代码转换为数字
- python - 从十六进制转换为颜色名称 Python
- python - 在Python中的文本文件中逐行查找行尾
- django - 为什么我在将文件上传到互联网速度较慢的服务器时收到 ERR_HTTP2_PING_FAILED?
- html - 如何使嵌套的flex子可滚动
- python - numpy 数组迭代中的元素不受 replace() 的影响
- python - 根据用户输入进行计算
- android-coordinatorlayout - 填充 CoordinatorLayout 内的空白空间
- javascript - 根据鼠标在屏幕上的位置控制字体粗细