简体   繁体   English

无法在颤动中访问提供程序

[英]Not able to access the provider in flutter

I have a simple provider class:-我有一个简单的提供者类:-

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

I am attaching this provider to the following class:-我将此提供程序附加到以下类:-

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!")
         ),
       ),
     ),
   }

and its Giving me the following error:-它给了我以下错误:-

 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. 

What could be the reason for this?这可能是什么原因?

Edit:- It's working fine when I access the provider from any child widget of the widget where I have defined.编辑:-当我从我定义的小部件的任何子小部件访问提供程序时,它工作正常。 ChangeNotifierProvider . ChangeNotifierProvider

You need to wrap your raisedButton in a Consumer .您需要将您的raisedButton包装在Consumer

The Consumer widget has two main purposes:消费者小部件有两个主要目的:

It allows obtaining a value from a provider when we don't have a BuildContext that is a descendant of said provider, and therefore cannot use Provider.of.当我们没有作为所述提供者的后代的 BuildContext 时,它允许从提供者获取值,因此不能使用 Provider.of。 This scenario typically happens when the widget that creates the provider is also one of its consumers, like in the following example:当创建提供者的小部件也是其消费者之一时,通常会发生这种情况,如下例所示:

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

This example will throw a ProviderNotFoundException, because Provider.of is called with a BuildContext that is an ancestor of the provider.此示例将抛出 ProviderNotFoundException,因为 Provider.of 是使用作为提供者的祖先的 BuildContext 调用的。

Instead, we can use the Consumer widget, that will call Provider.of with its own BuildContext.相反,我们可以使用 Consumer 小部件,它将使用自己的 BuildContext 调用 Provider.of。

Using Consumer, the previous example will become:使用Consumer,前面的例子会变成:

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

This won't throw a ProviderNotFoundException and will correctly build the Text.这不会抛出 ProviderNotFoundException 并且会正确构建文本。 It will also update the Text whenever the value foo changes.每当值 foo 更改时,它也会更新文本。

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

This is because you are calling Provider.of<DataProvider>(context).updateCount() using the wrong context .这是因为您使用错误的context调用Provider.of<DataProvider>(context).updateCount() You are using the context provided by the build method, which is higher up the hierarchy than the Provider you are trying to access.您正在使用由build方法提供的context ,该context比您尝试访问的 Provider 更高。 You need to use a context that belongs to a descendant (lower down the hierarchy) of the Provider.您需要使用属于 Provider 的后代(层次结构较低)的context

Wrap your Scaffold in a Builder widget, which exposes a new context at that level in the widget hierarchy, and use that context instead.将您的Scaffold包装在Builder小部件中,它会在小部件层次结构中的该级别公开一个新context ,并改为使用该上下文。

You could also use a Consumer , although it would not be optimal in your example because Consumer will rebuild every time notifyListeners() is called in the Provider, which would be redundant because your UI does not change.您也可以使用Consumer ,尽管在您的示例中它不是最佳选择,因为每次在 Provider 中调用notifyListeners()Consumer都会重建,这将是多余的,因为您的 UI 不会更改。

Having the Scaffold inside the Builder widget helped me to resolve the issue with Provider在 Builder 小部件中使用 Scaffold 帮助我解决了 Provider 的问题

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM