无法快速访问提供者

时间:2020-02-23 08:00:42

标签: flutter provider

我有一个简单的提供程序类:-

class DataProvider with ChangeNotifier {
   int count;
   void updateCount() {
     count = count + 1;
     notifyListeners();
   }
}

我正在将此提供程序附加到以下课程:-

class MyWidget extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => DataProvider(),
      child: Scaffold(
        body: raisedButton(
          onPressed: () {
            Provider.of<DataProvider>(context).updateCount();
          }
           child: Text("Click!")
         ),
       ),
     ),
   }

及其以下错误:-

 I/flutter (32011): Error: Could not find the correct Provider<DataProvider> above this MyWidget 
 Widget
 I/flutter (32011): To fix, please:
 I/flutter (32011):   * Ensure the Provider<DataProvider> is an ancestor to this MyWidget Widget
 I/flutter (32011):   * Provide types to Provider<DataProvider>
 I/flutter (32011):   * Provide types to Consumer<DataProvider>
 I/flutter (32011):   * Provide types to Provider.of<DataProvider>()
 I/flutter (32011):   * Ensure the correct `context` is being used. 

这可能是什么原因?

修改:- 当我从定义的窗口小部件的任何子窗口小部件访问提供程序时,它工作正常。 ChangeNotifierProvider

3 个答案:

答案 0 :(得分:1)

您需要将raisedButton包裹在Consumer中。

Consumer小部件有两个主要用途:

它允许我们在没有供应商的情况下从提供商那里获得价值 BuildContext是所述提供程序的后代,因此 无法使用Provider.of。这种情况通常发生在 创建提供程序的小部件也是其消费者之一,例如 以下示例:

@override
Widget build(BuildContext context) {
  return ChangeNotifierProvider(
    create: (_) => Foo(),
    child: Text(Provider.of<Foo>(context).value),
  );
}

此示例将引发ProviderNotFoundException,因为 使用BuildContext调用Provider.of,该BuildContext是 提供者。

相反,我们可以使用Consumer小部件,它将调用Provider.of 拥有自己的BuildContext。

使用Consumer,前面的示例将变为:

@override
Widget build(BuildContext context) {
  return ChangeNotifierProvider(
    create: (_) => Foo(),
    child: Consumer<Foo>(
      builder: (_, foo, __) => Text(foo.value),
    },
  );
}

这不会引发ProviderNotFoundException并将正确构建 文本。每当foo值更改时,它还将更新Text。

请参阅:https://pub.dev/documentation/provider/latest/provider/Consumer-class.html

答案 1 :(得分:1)

这是因为您使用错误的Provider.of<DataProvider>(context).updateCount()来呼叫context。您正在使用context方法提供的build,该方法在层次结构中比您尝试访问的提供者要高。您需要使用属于提供者的后代(在层次结构中较低)的context

Scaffold包装在Builder小部件中,这将在小部件层次结构中的该级别上显示一个新的context,并使用该上下文。

您也可以使用Consumer,尽管在您的示例中它不是最佳选择,因为每次在Provider中调用Consumer时,notifyListeners()都会重新生成,这将是多余的,因为您的用户界面不会改变。

答案 2 :(得分:0)

Builder小部件内有脚手架有助于我解决提供程序的问题

Widget build(BuildContext context) {
    return ChangeNotifierProvider<StatusViewModel>(
      create: (context) => StatusViewModel(),
  child: Builder(
    builder: (context){
      return Scaffold(
        appBar: AppBar(
          title: Text("this is appbar"),    
        ),
      );
    },
  ),
);}