Problem in using Provider in flutter when listen:true

Viewed 8024

I'm working on an app in Flutter. I try to use Provider in the app but have faced this error:

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. but I think this is not a good way to solve this problem. Also, I need provider to listen. I have searched the internet but could not find any suitable solution.

This is my Flutter Doctor:

[√] 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.

6 Answers

The error clearly says your declaring it out side of the Widget tree. 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.

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. 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).

check this video mate. He uses the same approach as you did

If listen should ways be true, provider wouldn't have this flag.

The situation you are in requires listen:false for a reason. It is the correct solution here.

I just changed that

Provider.of(context);

to

context.watch();

Note: Provider can listen only on build() and didChangeDependencies() methods. In initState() method doesn't work.

I just changed

Provider.of<YourProvider>(context);

to

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

Setting listen to false is not bad practice. 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) => 
Related