简体   繁体   English

listen:true 时在 flutter 中使用 Provider 的问题

[英]Problem in using Provider in flutter when listen:true

I'm working on an app in Flutter. I try to use Provider in the app but have faced this error:我正在 Flutter 开发一个应用程序。我尝试在应用程序中使用 Provider 但遇到了这个错误:

Tried to listen to a value exposed with provider, from outside of the widget tree.
E/flutter ( 2850): 
E/flutter ( 2850): This is likely caused by an event handler (like a button's onPressed) that called
E/flutter ( 2850): Provider.of without passing `listen: false`.
E/flutter ( 2850): 
E/flutter ( 2850): To fix, write:
E/flutter ( 2850): Provider.of<Complexes>(context, listen: false);
E/flutter ( 2850): 
E/flutter ( 2850): It is unsupported because may pointlessly rebuild the widget associated to the
E/flutter ( 2850): event handler, when the widget tree doesn't care about the value.

My code is:我的代码是:

loadedComplexes = Provider.of<Complexes>(context, listen: true).favoriteItems;

When is set to listen:false , the problem solved.当设置为listen:false时,问题解决。 but I think this is not a good way to solve this problem.但我认为这不是解决这个问题的好方法。 Also, I need provider to listen.另外,我需要提供者倾听。 I have searched the inte.net but could not find any suitable solution.我搜索了 inte.net 但找不到任何合适的解决方案。

This is my Flutter Doctor:这是我的 Flutter 医生:

[√] Flutter (Channel stable, v1.12.13+hotfix.7, on Microsoft Windows [Version 10.0.18363.657],    locale en-US)
   • Flutter version 1.12.13+hotfix.7 at C:\android\flutter
   • Framework revision 9f5ff2306b (6 weeks ago), 2020-01-26 22:38:26 -0800
   • Engine revision a67792536c
   • Dart version 2.7.0

[√] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    • Android SDK at C:/android/sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 28.0.3
    • ANDROID_HOME = C:/android/sdk
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b04)
    • All Android licenses accepted.

[√] Android Studio (version 3.6)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 43.0.2
    • Dart plugin version 192.7761
    • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b04)

[√] IntelliJ IDEA Ultimate Edition (version 2019.3)
    • IntelliJ at C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.4
    • Flutter plugin version 42.1.4
    • Dart plugin version 193.5731

[!] VS Code (version 1.41.1)
    • VS Code at C:\Users\Altay\AppData\Local\Programs\Microsoft VS Code
    X Flutter extension not installed; install from
      https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[√] Connected device (1 available)
    • Android SDK built for x86 • emulator-5554 • android-x86 • Android 5.0.2 (API 21) (emulator)

! Doctor found issues in 1 category.
Process finished with exit code 0

My provider block:我的提供商块:

return MultiProvider(
  providers: [
    ChangeNotifierProvider(
      create: (ctx) => Salons(),
    ),
    ChangeNotifierProvider(
      create: (ctx) => Cities(),
    ),
    ChangeNotifierProvider(
      create: (ctx) => Auth(),
    ),
    ChangeNotifierProvider(
      create: (ctx) => Complexes(),
    ),
    ChangeNotifierProvider(
      create: (ctx) => UserInfo(),
    ),
    ChangeNotifierProvider(
      create: (ctx) => User(),
    ),
  ],
  child: MaterialApp(........

The method which call the provider:调用提供者的方法:

Future<void> _submit() async {
    loadedComplexes.clear();
    loadedComplexes =
        Provider.of<Complexes>(context, listen: true).favoriteItems;
    loadedComplexestolist.addAll(loadedComplexes);
}

I can provide more information if it's necessary.如果有必要,我可以提供更多信息。 Is there any solution for this problem?这个问题有什么解决办法吗?

Thanks in advance.提前致谢。

The error clearly says your declaring it out side of the Widget tree.该错误清楚地表明您在Widget树之外声明它。 If you want to set listen to true then you must declare it inside the Widget tree so that the provider knows which Widget tree has to be rebuilt when changes occur.如果您想将listen设置为 true,那么您必须在Widget树中声明它,以便提供者知道在发生更改时必须重建哪个Widget树。

Example例子

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
 loadedComplexes = Provider.of<Complexes>(context, listen: true).favoriteItems;//You must declare here if listen to true
  return Scaffold(
    body: Center(
      child: MyWidget(),
    ),
 );

} } } }

Setting listen to true makes the whole widget as a listener and leads to rebuilding the whole widget tree.listen设置为true会使整个小部件成为侦听器,并导致重建整个小部件树。 But setting listen to false will help you to rebuild a particular widget which you declared as a Consumer (a consumer is a widget which listen for changes).但是将 listen 设置为false将帮助您重建一个您声明为Consumer的特定小部件(消费者是一个监听变化的小部件)。

check this video mate.检查这个视频伙伴。 He uses the same approach as you did他用的方法和你一样

If listen should ways be true , provider wouldn't have this flag.如果listen方法为true ,则 provider 不会有此标志。

The situation you are in requires listen:false for a reason.您所处的情况需要listen:false是有原因的。 It is the correct solution here.这是正确的解决方案。

I just changed that我只是改变了

Provider.of(context); Provider.of(上下文);

to

context.watch();上下文。手表();

Note : Provider can listen only on build() and didChangeDependencies() methods.注意:Provider 只能监听 build() 和 didChangeDependencies() 方法。 In initState() method doesn't work.在 initState() 方法中不起作用。

I just changed我刚刚改变

Provider.of<YourProvider>(context);

to

Provider.of<YourProvider>(context,listen: false);

Setting listen to false is not bad practice.将 listen 设置为 false 是不错的做法。 It is used when accessing a provider value once, or calling a provider method.它在访问一次提供程序值或调用提供程序方法时使用。

If you want to listen to updates, you have the choice between a number of different providers .如果您想收听更新,您可以在多个不同的提供商之间进行选择。

Replace this snippet of your code替换这段代码

create: (ctx) =>

whith蒙山

create: (ctx, listen: false) => 

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

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