Search code examples
flutterflutter-provider

How listen: false works in provider package in flutter?


I made a program that shows a counter in the center of the screen. When you press the plus button the value of the counter should increase.

This is the code I made first:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<CountProvider>(
          create: (_) => CountProvider(),
        ),
      ],
      child: MaterialApp(
        home: HomePage(),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Anand Jangid'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Center(
            child: Text(
              Provider.of<CountProvider>(context).count.toString(),
              style: const TextStyle(
                fontSize: 50,
                fontWeight: FontWeight.w700,
              ),
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          Provider.of<CountProvider>(context).updaterCounter();
        },
      ),
    );
  }
}

class CountProvider extends ChangeNotifier {
  int _count = 0;

  int get count => _count;

  void updaterCounter(){
    _count++;
    notifyListeners();
  }
}

In output the counter was not changing on the screen. But when I introduced listen: false in the FloatingActionButton provider it started working.

Updated code:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<CountProvider>(
          create: (_) => CountProvider(),
        ),
      ],
      child: MaterialApp(
        home: HomePage(),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Anand Jangid'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Center(
            child: Text(
              Provider.of<CountProvider>(context).count.toString(),
              style: const TextStyle(
                fontSize: 50,
                fontWeight: FontWeight.w700
              ),
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          Provider.of<CountProvider>(context, listen: false).updaterCounter();
        },
      ),
    );
  }
}

class CountProvider extends ChangeNotifier {
  int _count = 0;

  int get count => _count;

  void updaterCounter(){
    _count++;
    notifyListeners();
  }
}

Now I am getting the desired result.

I was expecting a number that appears on the center of the screen which changes when I press the plus button.


Solution

  • Well, when you don't put listen: false, look into your console, you will see an error, and it will say exactly why that doesn't work:

    Tried to listen to a value exposed with provider, from outside of the widget tree.
    
    This is likely caused by an event handler (like a button's onPressed) that called
    Provider.of without passing `listen: false`.
    
    To fix, write:
    Provider.of<CountProvider>(context, listen: false);
    
    It is unsupported because may pointlessly rebuild the widget associated to the
    event handler, when the widget tree doesn't care about the value.
    
    The context used was: HomePage(dependencies: [_InheritedProviderScope<CountProvider?>])