ProviderNotFoundException was thrown building Consumer

huangapple go评论54阅读模式
英文:

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&lt;SubTemasScreen&gt; createState() =&gt; _SubTemasScreenState();
}
class _SubTemasScreenState extends State&lt;SubTemasScreen&gt; {
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 &amp;&amp; timer!.isActive) return;
timer = Timer.periodic(const Duration(seconds: 5), (timer) {
//job
setState(() {});
});
}
bool _esActivo = true;
String miEmail = &quot;&quot;;
Future getData() async {
var url = Constantes().urlAPI + &quot;get_datos_usuario.php&quot;;
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(&quot;miEmail es ${miEmail}&quot;);
for (var i = 0; i &lt; data.length; i++) {
String s = data![i][&quot;email&quot;];
if (s == miEmail) {
var activo = data![i][&quot;activo&quot;];
print(&quot;activo ${activo}&quot;);
if (activo == &quot;1&quot;) {
_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&lt;bool&gt; _onWillPop() async {
return false; //&lt;-- SEE HERE
}
@override
Widget build(BuildContext context) {
var filtrado = &quot;0&quot;;
return _esActivo
? WillPopScope(
onWillPop: _onWillPop,
child: SafeArea(
child: Scaffold(
body: Consumer&lt;TemasProvider&gt;(
builder: (context, proveedor, _) {
return Column(
children: [
FilaSuperiorPantallas(),
SizedBox(
height: 15,
),
BuscadorTextField(
controller: _controller,
hintText: &quot;Buscar sub-temas por t&#237;tulo&quot;,
),
SizedBox(
height: 8,
),
//lista de temas para filtrar subtemas
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(&quot;Selecciona un tema para filtrar&quot;),
filtrado != &quot;0&quot;
? 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&lt;Null&gt; refresh() async {
await Future.delayed(Duration(seconds: 2));
setState(() {});
}
}

I am getting the following exception at line:

  body: Consumer&lt;TemasProvider&gt;(
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: &#39;MYSTERYMAP ADMIN&#39;,
theme: ThemeData(
primarySwatch: Colors.grey,
),
home: MultiProvider(providers: [
ChangeNotifierProvider(create: (_) =&gt; AutenticacionProvider()),
ChangeNotifierProvider(create: (_) =&gt; TemasProvider()),
], child: WidgetTree()),
);
}
}

This is the exception output:

======== Exception caught by widgets library =======================================================
The following ProviderNotFoundException was thrown building Consumer&lt;TemasProvider&gt;:
Error: Could not find the correct Provider&lt;TemasProvider&gt; above this Consumer&lt;TemasProvider&gt; 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 &quot;scoped&quot;. 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&lt;TemasProvider&gt; is under your MultiProvider/Provider&lt;TemasProvider&gt;.
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= &quot;0&quot;;
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: (_) =&gt; AutenticacionProvider()),
ChangeNotifierProvider(create: (_) =&gt; TemasProvider()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: &#39;MYSTERYMAP ADMIN&#39;,
theme: ThemeData(
primarySwatch: Colors.grey,
),
home: WidgetTree(),
),
);
}
}

huangapple
  • 本文由 发表于 2023年5月22日 19:46:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76305846.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定