flutterdartshopping-cartchangenotifierflutter-change-notifier-provider

My Counter made with ChangeNotifier Provider replicates its value with other Counter Instances


I am creating a counter for a shopping cart. The problem is when the value of one counter changes, it affects all the other counters on the screen. I used ChangeNotifier and I have no idea what I am doing wrong.

This is the Counter Model

import 'package:flutter/material.dart';

class CounterModel extends ChangeNotifier {
  int _count = 0;
  int get getCount => _count;

  void increment() {
    if (_count >= 0) {
      _count++;
    }
    notifyListeners();
  }

  void decrease() {
    if (_count > 0) {
      _count--;
    }
    notifyListeners();
  }
}

This is the build of the Counter

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

class ProvideCount extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = Provider.of<CounterModel>(context);
    return Row(
      children: <Widget>[
        IconButton(icon: Icon(Icons.add), onPressed: counter.increment),
        Text('${counter.getCount}'),
        IconButton(icon: Icon(Icons.remove), onPressed: counter.decrease),
      ],
    );
  }
}

And this is the main.dart file

import 'package:flutter/material.dart';
import 'package:provide_count/counter_model.dart';
import 'package:provide_count/providecount.dart';
import 'package:provider/provider.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<CounterModel>(create: (_) => CounterModel()),
      ],
      child: MaterialApp(
        title: 'Flutter Demo',
        home: SafeArea(
          top: true,
          child: Scaffold(
            body: Column(
              children: [
                ProvideCount(),
                ProvideCount(),
                ProvideCount(),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Solution

  • The problem is that you have a ChangeNotifierProvider at the top of your tree.

    When you call Provider.of<CounterModel>, You are searching for the closest Provider widget on the tree, Which is the same for all of the widgets. So they sync up.

    If you don't want this to happen, you could stop using Provider, or you could at least wrap each ProvideCount with their own Provider:

    return MaterialApp(
          title: 'Flutter Demo',
          home: SafeArea(
            top: true,
            child: Scaffold(
              body: Column(
                children: [
                  ChangeNotifierProvider<CounterModel>(
                    create: (_) => CounterModel()
                    child: ProvideCount(),
                  ),
                  ChangeNotifierProvider<CounterModel>(
                    create: (_) => CounterModel()
                    child: ProvideCount(),
                  ),
                  ChangeNotifierProvider<CounterModel>(
                    create: (_) => CounterModel()
                    child: ProvideCount(),
                  ),
                ],
              ),
            ),
          ),
        );