"Could not find the correct Provider" 即使小部件也是在 Provider 添加到上下文之后构建的
"Could not find the correct Provider" even the widget is built after the Provider is added to context
我在尝试从提供商处获取数据时遇到问题。我和他们一起工作了很多次,所以我知道你可能遇到的所有常见错误,但这个错误让我抓狂。
我有一个简单的小部件,它从 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
并在子部分中添加了一个 Builder,它接收一个包含两个文本的列,显示一些 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()
时出现错误 Could not find the correct Provider<PassesSelectorManager> above this PassesSelector widget
但我不明白为什么,就像收到的上下文没有提供者一样。我知道如果你推送一条路线,上下文会有所不同,但在这种情况下,我们只是向上下文添加一个小部件......
你可能想知道的事情:
- [√] Flutter(频道稳定,2.10.2,在 Microsoft Windows [版本 10.0.19042.1526],语言环境 en-GB)
- [√] VS Code(版本 1.65.2)
- [√] Android 工具链 - 为 Android 设备开发(Android SDK 版本 30.0.2)
到目前为止我尝试过的事情:
- 使用 MultiProvider 的
builder(context, child) => PassesSelector()
函数代替 child
- 在 Builder 列中添加
Consumer<PassesSelector>
并添加 PassesSelector()
作为 child
- 在
PassesSelector()
的构建函数中添加Consumer<PassesSelector>
- 将所有带有
Texts
和 PassesSelector
的 Column 作为一个新的 Widget 放置,同样的情况发生,Texts 可以正确显示数据但是 widget PassesSelector()
抛出错误。
感谢任何帮助,谢谢!
我建议尝试将上下文的 PassesSelectorManager
提供程序传递给 PassesSelector
。我认为您需要 watch
而不是 read
但我不知道您的 PassesSelectorManager
中有什么,例如是否有任何 notifyListeners
调用。试试这个代码:
class PassesSelector extends StatelessWidget {
final PassesSelectorManager passesSelectionManager;
const PassesSelector({required this.passesSelectionManager, Key? key})
: super (key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
DaysSelector(
primaryColor: Colors.green,
title: "Select pass",
passDays: passesSelectionManager.passes,
),
],
);
}
}
class TicketSelectionPresenter extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<PassesSelectorManager>(
create: (_) => PassesSelectorManager()
),
],
builder: (context, child) {
final passesSelectionManager = context.watch<PassesSelectorManager>();
return Column(
children: [
passesSelectionManager.taxes.toString()),
passesSelectionManager.dayPasses.toString()),
PassesSelector(passesSelectionManager),
],
);
}),
);
}
}
编辑:ListenableProvider
的另一种方法:
你可以尝试使用ListenableProvider,这不是经常使用,但在某些情况下会很有用。删除我在原始答案中建议的 passesSelectionManager
成员表单 PassesSelector
class 和构造函数,然后试试这个:
class TicketSelectionPresenter extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<PassesSelectorManager>(
create: (_) => PassesSelectorManager()
),
],
builder: (context, child) {
final passesSelectionManager = context.watch<PassesSelectorManager>();
return Column(
children: [
passesSelectionManager.taxes.toString()),
passesSelectionManager.dayPasses.toString()),
// this is the new part
ListenableProvider<PassesSelectorManager>.value(
value: passesSelectionManager,
child: PassesSelector()),
],
);
}),
);
}
}
几天来我们一直在处理其他事情,但我们又遇到了一个奇怪的错误,因为 Flutter/Provider 没有按预期工作。我们再次进行了大量研究,直到找到解决方案。
导入文件时,Visual Studio代码导入了一些小写的单词,而目录名称以大写字母开头。因此,创建提供程序的页面是从中实例化它的(这是一个示例,请注意 Providers 单词的书写方式):
import 'package:xxx/Application/Providers/pass_selector_manager.dart
当小部件阅读试图从以下位置获取它时:
import 'package:xxx/Application/providers/pass_selector_manager.dart
我们觉得很傻,我们一直在检查生成的每个小部件树和周围所有“困难”的东西,直到我们发现这一点。这几乎是一个模因,但好吧,最后,教训是在出现问题时检查你的导入,即使它们是自动导入的。
我在尝试从提供商处获取数据时遇到问题。我和他们一起工作了很多次,所以我知道你可能遇到的所有常见错误,但这个错误让我抓狂。
我有一个简单的小部件,它从 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
并在子部分中添加了一个 Builder,它接收一个包含两个文本的列,显示一些 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()
时出现错误 Could not find the correct Provider<PassesSelectorManager> above this PassesSelector widget
但我不明白为什么,就像收到的上下文没有提供者一样。我知道如果你推送一条路线,上下文会有所不同,但在这种情况下,我们只是向上下文添加一个小部件......
你可能想知道的事情:
- [√] Flutter(频道稳定,2.10.2,在 Microsoft Windows [版本 10.0.19042.1526],语言环境 en-GB)
- [√] VS Code(版本 1.65.2)
- [√] Android 工具链 - 为 Android 设备开发(Android SDK 版本 30.0.2)
到目前为止我尝试过的事情:
- 使用 MultiProvider 的
builder(context, child) => PassesSelector()
函数代替child
- 在 Builder 列中添加
Consumer<PassesSelector>
并添加PassesSelector()
作为 child - 在
PassesSelector()
的构建函数中添加 - 将所有带有
Texts
和PassesSelector
的 Column 作为一个新的 Widget 放置,同样的情况发生,Texts 可以正确显示数据但是 widgetPassesSelector()
抛出错误。
Consumer<PassesSelector>
感谢任何帮助,谢谢!
我建议尝试将上下文的 PassesSelectorManager
提供程序传递给 PassesSelector
。我认为您需要 watch
而不是 read
但我不知道您的 PassesSelectorManager
中有什么,例如是否有任何 notifyListeners
调用。试试这个代码:
class PassesSelector extends StatelessWidget {
final PassesSelectorManager passesSelectionManager;
const PassesSelector({required this.passesSelectionManager, Key? key})
: super (key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
DaysSelector(
primaryColor: Colors.green,
title: "Select pass",
passDays: passesSelectionManager.passes,
),
],
);
}
}
class TicketSelectionPresenter extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<PassesSelectorManager>(
create: (_) => PassesSelectorManager()
),
],
builder: (context, child) {
final passesSelectionManager = context.watch<PassesSelectorManager>();
return Column(
children: [
passesSelectionManager.taxes.toString()),
passesSelectionManager.dayPasses.toString()),
PassesSelector(passesSelectionManager),
],
);
}),
);
}
}
编辑:ListenableProvider
的另一种方法:
你可以尝试使用ListenableProvider,这不是经常使用,但在某些情况下会很有用。删除我在原始答案中建议的 passesSelectionManager
成员表单 PassesSelector
class 和构造函数,然后试试这个:
class TicketSelectionPresenter extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<PassesSelectorManager>(
create: (_) => PassesSelectorManager()
),
],
builder: (context, child) {
final passesSelectionManager = context.watch<PassesSelectorManager>();
return Column(
children: [
passesSelectionManager.taxes.toString()),
passesSelectionManager.dayPasses.toString()),
// this is the new part
ListenableProvider<PassesSelectorManager>.value(
value: passesSelectionManager,
child: PassesSelector()),
],
);
}),
);
}
}
几天来我们一直在处理其他事情,但我们又遇到了一个奇怪的错误,因为 Flutter/Provider 没有按预期工作。我们再次进行了大量研究,直到找到解决方案。
导入文件时,Visual Studio代码导入了一些小写的单词,而目录名称以大写字母开头。因此,创建提供程序的页面是从中实例化它的(这是一个示例,请注意 Providers 单词的书写方式):
import 'package:xxx/Application/Providers/pass_selector_manager.dart
当小部件阅读试图从以下位置获取它时:
import 'package:xxx/Application/providers/pass_selector_manager.dart
我们觉得很傻,我们一直在检查生成的每个小部件树和周围所有“困难”的东西,直到我们发现这一点。这几乎是一个模因,但好吧,最后,教训是在出现问题时检查你的导入,即使它们是自动导入的。