“无法找到正确的提供商”甚至在将 Provider 添加到上下文之后构建小部件
我在尝试从提供商处获取数据时遇到问题。我和他们一起工作了很多次,所以我知道你可能会遇到的所有常见错误,但这一个让我发疯。
我有一个简单的小部件,可以从 PassesSelector
提供程序获取数据:
class PassesSelector extends StatelessWidget {
@override
Widget build(BuildContext context) {
List<Passes> passes = Provider.of<PassesSelectorManager>(context).passes;
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
DaysSelector(
primaryColor: Colors.green,
title: "Select pass",
passDays: passes,
),
],
);
}
}
在另一个小部件中,我创建一个 Multiprovider(因为需要更多提供程序),在其中初始化 PassesSelector
并在孩子,我添加一个生成器,它接收一个包含两个文本的列,显示一些 PassesSelector Provider 数据和 PassSelector
小部件:
class TicketSelectionPresenter extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<PassesSelectorManager>(
create: (_) => PassesSelectorManager()
),
],
child: Builder(builder: (context) {
return Column(
children: [
Text(context.read<PassesSelectorManager>().taxes.toString()),
Text(context.read<PassesSelectorManager>().dayPasses.toString()),
PassesSelector(),
],
);
}),
);
}
}
问题是列内的 Texts
正确显示信息(所以,提供程序已创建),但在渲染 PassesSelector()
时,我收到错误无法找到正确的 Provider
但我不明白为什么,就像收到的上下文没有提供者一样。我知道如果您推送路线,上下文会有所不同,但在这种情况下,我们只是向上下文添加一个 Widget...
您可能想知道的事情:
- [√] Flutter(Channel stable,2.10.2,on Microsoft Windows [版本 10.0.19042.1526],语言环境 en-GB)
- [√] VS Code(版本 1.65.2)
- [√] Android 工具链 - 为 Android 设备开发(Android SDK 版本) 30.0.2)
到目前为止我尝试过的事情:
- 使用
builder(context, child) => MultiProvider 的 PassesSelector()
函数而不是child
- 在 Builder 列中添加
Consumer
并将PassesSelector()
添加为子项 - 在
PassesSelector()
的构建函数中添加Consumer
- 放置所有带有
Texts
的列并PassesSelector
作为一个新的 Widget,同样的情况发生,文本可以正确显示数据,但小部件PassesSelector()
会抛出错误。
如有任何帮助,我们将不胜感激,谢谢!
I'm having problems trying to obtain data from a provider. I've been working a lot with them so I know all the usual errors that you can get with, but this one is driving me crazy.
I have a simple widget that gets data from PassesSelector
provider:
class PassesSelector extends StatelessWidget {
@override
Widget build(BuildContext context) {
List<Passes> passes = Provider.of<PassesSelectorManager>(context).passes;
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
DaysSelector(
primaryColor: Colors.green,
title: "Select pass",
passDays: passes,
),
],
);
}
}
In another widget, I create a Multiprovider (as there will be more providers needed) where I initialize the PassesSelector
and in child, I add a Builder that receives a column with two texts showing some PassesSelector Provider data and the PassSelector
widget:
class TicketSelectionPresenter extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<PassesSelectorManager>(
create: (_) => PassesSelectorManager()
),
],
child: Builder(builder: (context) {
return Column(
children: [
Text(context.read<PassesSelectorManager>().taxes.toString()),
Text(context.read<PassesSelectorManager>().dayPasses.toString()),
PassesSelector(),
],
);
}),
);
}
}
The thing is that the Texts
inside the Column show the information properly (so, the provider is created) but when rendering the PassesSelector()
I'm getting the error Could not find the correct Provider<PassesSelectorManager> above this PassesSelector widget
but I don't understand why, like the context received did not have the provider. I know the context is different if you push a route, but in this case we're just adding a Widget to the context...
Things you might want to know:
- [√] Flutter (Channel stable, 2.10.2, on Microsoft Windows [Version 10.0.19042.1526], locale en-GB)
- [√] VS Code (version 1.65.2)
- [√] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
Things I tried so far:
- Using the
builder(context, child) => PassesSelector()
function of MultiProvider instead ofchild
- Add
Consumer<PassesSelector>
inside the Builder column and addPassesSelector()
as child - Add
Consumer<PassesSelector>
inside the build function ofPassesSelector()
- Placed all the Column with
Texts
andPassesSelector
as a new Widget, and the same happens, the Texts can show the data properly but the widgetPassesSelector()
throws the error.
Any help is appreciated, thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我建议尝试将上下文的
PassesSelectorManager
提供程序传递给PassesSelector
。我认为您需要watch
而不是read
,但我不知道您的PassesSelectorManager
中有什么,例如是否有notifyListeners< /代码> 调用。试试这个代码:
编辑:使用
ListenableProvider
的另一种方法:您可以尝试使用ListenableProvider,这个不经常使用,但在某些情况下很有用。删除我在原始答案中建议的
passesSelectionManager
成员表单PassesSelector
类和构造函数,然后尝试以下操作:I would suggest to try to pass the context's
PassesSelectorManager
provider toPassesSelector
. I think you needwatch
and notread
but I don't know what's in yourPassesSelectorManager
, for example are there anynotifyListeners
called. Try this code:EDIT: another approach with
ListenableProvider
:You can try to use ListenableProvider, this is not used very often but can be useful in some cases. Remove the
passesSelectionManager
member formPassesSelector
class and constructor I suggested in the original answer, and try this:我们已经花了几天时间处理其他事情,但我们再次遇到了一个奇怪的错误,因为 Flutter/Provider 没有按预期工作。我们再次进行了大量研究,直到找到解决方案。
导入文件时,Visual Studio Code 会导入一些小写单词,而目录名称以大写字母开头。因此,创建提供程序的页面正在实例化它(这是一个示例,请注意 Providers 一词是如何编写的):
而 Widget 读取试图从中获取它:
我们觉得很傻,我们我们一直在检查生成的每个小部件树以及周围所有“困难”的东西,直到我们发现这一点。这几乎是一个模因,但最后,教训是在出现问题时检查您的导入,即使它们是自动导入的。
We've been a few days working on other things and we got again a weird error as Flutter/Provider was not working as expected. We did big research again until we found the solution.
When importing files, Visual Studio Code was importing some words in lower case while the directory name started with Caps. So, the page that was creating the provider was instantiating it from (it's an example, notice how the Providers word is written):
while the Widget reading was trying to obtain it from:
We feel silly, we've been checking each widget tree generated and all the "hard" stuff around until we found out this. It's almost a meme, but well, at the end, the lesson is to check your imports when something breaks, even if they're auto imported.