英文:
ProviderNotFoundException was thrown building Consumer
问题
以下是您的Flutter应用中的代码的翻译部分:
我在我的Flutter应用程序中有以下类:
class SubTemasScreen extends StatefulWidget {
const SubTemasScreen({Key? key}) : super(key: key);
@override
State<SubTemasScreen> createState() => _SubTemasScreenState();
}
class _SubTemasScreenState extends State<SubTemasScreen> {
final TextEditingController _controller = TextEditingController();
Timer? timer;
bool verTodos = true;
bool verActivos = false;
bool verNoActivos = false;
bool verAdmin = false;
bool verCosmicos = false;
bool verMecenas = false;
bool verVerificados = false;
bool verNoVerificados = false;
void initTimer() {
if (timer != null && timer!.isActive) return;
timer = Timer.periodic(const Duration(seconds: 5), (timer) {
//job
setState(() {});
});
}
bool _esActivo = true;
String miEmail = "";
Future getData() async {
var url = Constantes().urlAPI + "get_datos_usuario.php";
http.Response response = await http.get(Uri.parse(url));
List data = json.decode(response.body);
User? usuarioActual = FirebaseAuth.instance.currentUser;
if (usuarioActual != null) {
miEmail = usuarioActual.email!;
print("miEmail es ${miEmail}");
for (var i = 0; i < data.length; i++) {
String s = data![i]["email"];
if (s == miEmail) {
var activo = data![i]["activo"];
print("activo ${activo}");
if (activo == "1") {
_esActivo = true;
} else {
_esActivo = false;
}
}
}
}
}
@override
void initState() {
super.initState();
getEmailUsuarioActual();
initTimer();
}
@override
void dispose() {
timer?.cancel();
super.dispose();
}
getEmailUsuarioActual() {
getData();
}
//避免返回按钮
Future<bool> _onWillPop() async {
return false; // <---看这里
}
@override
Widget build(BuildContext context) {
var filtrado = "0";
return _esActivo
? WillPopScope(
onWillPop: _onWillPop,
child: SafeArea(
child: Scaffold(
body: Consumer<TemasProvider>(
builder: (context, proveedor, _) {
return Column(
children: [
FilaSuperiorPantallas(),
SizedBox(
height: 15,
),
BuscadorTextField(
controller: _controller,
hintText: "Buscar sub-temas por título",
),
SizedBox(
height: 8,
),
//lista de temas para filtrar subtemas
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text("Selecciona un tema para filtrar"),
filtrado != "0"
? IconButton(
onPressed: () {},
icon: Icon(
Icons.filter_alt_off_outlined,
size: 23,
))
: IconButton(
onPressed: () {},
icon: Icon(
Icons.filter_alt,
size: 23,
))
],
),
ListaTemasHorizontalLight(),
//LISTA DE sub TEMAS TODOS
ListaSubtemasTodos(controller: _controller)
],
);
}),
),
),
)
: NoActivo();
}
Future<Null> refresh() async {
await Future.delayed(Duration(seconds: 2));
setState(() {});
}
}
您遇到的问题似乎是Provider未被正确添加到BuildContext中。您需要确保Consumer<TemasProvider>
在MultiProvider/Provider<TemasProvider>
的范围内。您已经在MyApp
中添加了MultiProvider
,但是请确保所有与Consumer<TemasProvider>
相关的部分都位于MultiProvider
的子树内。
如果问题仍然存在,请检查您的Widget树是否按照正确的方式组织,以便Provider能够正确传递给Consumer
。如果问题仍然存在,请提供更多关于Widget树的信息,以便我可以提供更具体的帮助。
英文:
I have the following class in my Flutter app:
class SubTemasScreen extends StatefulWidget {
const SubTemasScreen({Key? key}) : super(key: key);
@override
State<SubTemasScreen> createState() => _SubTemasScreenState();
}
class _SubTemasScreenState extends State<SubTemasScreen> {
final TextEditingController _controller = TextEditingController();
Timer? timer;
bool verTodos = true;
bool verActivos = false;
bool verNoActivos = false;
bool verAdmin = false;
bool verCosmicos = false;
bool verMecenas = false;
bool verVerificados = false;
bool verNoVerificados = false;
void initTimer() {
if (timer != null && timer!.isActive) return;
timer = Timer.periodic(const Duration(seconds: 5), (timer) {
//job
setState(() {});
});
}
bool _esActivo = true;
String miEmail = "";
Future getData() async {
var url = Constantes().urlAPI + "get_datos_usuario.php";
http.Response response = await http.get(Uri.parse(url));
List data = json.decode(response.body);
User? usuarioActual = FirebaseAuth.instance.currentUser;
if (usuarioActual != null) {
miEmail = usuarioActual.email!;
print("miEmail es ${miEmail}");
for (var i = 0; i < data.length; i++) {
String s = data![i]["email"];
if (s == miEmail) {
var activo = data![i]["activo"];
print("activo ${activo}");
if (activo == "1") {
_esActivo = true;
} else {
_esActivo = false;
}
}
}
}
}
@override
void initState() {
super.initState();
getEmailUsuarioActual();
initTimer();
}
@override
void dispose() {
timer?.cancel();
super.dispose();
}
getEmailUsuarioActual() {
getData();
}
//EVITAR BACK BUTTON
Future<bool> _onWillPop() async {
return false; //<-- SEE HERE
}
@override
Widget build(BuildContext context) {
var filtrado = "0";
return _esActivo
? WillPopScope(
onWillPop: _onWillPop,
child: SafeArea(
child: Scaffold(
body: Consumer<TemasProvider>(
builder: (context, proveedor, _) {
return Column(
children: [
FilaSuperiorPantallas(),
SizedBox(
height: 15,
),
BuscadorTextField(
controller: _controller,
hintText: "Buscar sub-temas por título",
),
SizedBox(
height: 8,
),
//lista de temas para filtrar subtemas
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text("Selecciona un tema para filtrar"),
filtrado != "0"
? IconButton(
onPressed: () {},
icon: Icon(
Icons.filter_alt_off_outlined,
size: 23,
))
: IconButton(
onPressed: () {},
icon: Icon(
Icons.filter_alt,
size: 23,
))
],
),
ListaTemasHorizontalLight(),
//LISTA DE sub TEMAS TODOS
ListaSubtemasTodos(controller: _controller)
],
);
}),
),
),
)
: NoActivo();
}
Future<Null> refresh() async {
await Future.delayed(Duration(seconds: 2));
setState(() {});
}
}
I am getting the following exception at line:
body: Consumer<TemasProvider>(
builder: (context, proveedor, _) {
I have declared TemasProvider at the top of the widgets tree:
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'MYSTERYMAP ADMIN',
theme: ThemeData(
primarySwatch: Colors.grey,
),
home: MultiProvider(providers: [
ChangeNotifierProvider(create: (_) => AutenticacionProvider()),
ChangeNotifierProvider(create: (_) => TemasProvider()),
], child: WidgetTree()),
);
}
}
This is the exception output:
======== Exception caught by widgets library =======================================================
The following ProviderNotFoundException was thrown building Consumer<TemasProvider>:
Error: Could not find the correct Provider<TemasProvider> above this Consumer<TemasProvider> Widget
This happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:
- You added a new provider in your `main.dart` and performed a hot-reload.
To fix, perform a hot-restart.
- The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
- You used a `BuildContext` that is an ancestor of the provider you are trying to read.
Make sure that Consumer<TemasProvider> is under your MultiProvider/Provider<TemasProvider>.
This usually happens when you are creating a provider and trying to read it immediately.
EDIT
Here you TemasProvider class:
import 'package:flutter/material.dart';
class TemasProvider extends ChangeNotifier {
String temaActual= "0";
void cambiarTemaActualState(String s) {
temaActual = s;
notifyListeners();
}
}
答案1
得分: 1
If you want your provider(s) to be available everywhere in the widget tree (on all screens), you should provide it above the MaterialApp
widget. So, in your case, you should wrap your MaterialApp
widget with your MultiProvider
like this:
如果您希望您的提供程序在小部件树中的所有位置(在所有屏幕上)都可用,您应该将其提供在MaterialApp
小部件之上。因此,在您的情况下,您应该像这样包装您的MaterialApp
小部件以包含您的MultiProvider
:
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => AutenticacionProvider()),
ChangeNotifierProvider(create: (_) => TemasProvider()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'MYSTERYMAP ADMIN',
theme: ThemeData(
primarySwatch: Colors.grey,
),
home: WidgetTree(),
),
);
}
}
英文:
If you want your provider(s) to be available everywhere in the widget tree (on all screens), you should provide it above the MaterialApp
widget. So, in your case, you should wrap your MaterialApp
widget with your MultiProvider
like this:
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => AutenticacionProvider()),
ChangeNotifierProvider(create: (_) => TemasProvider()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'MYSTERYMAP ADMIN',
theme: ThemeData(
primarySwatch: Colors.grey,
),
home: WidgetTree(),
),
);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论