skip to Main Content

Is there a way to make a ChangeNotifier listen to another ChangeNotifier in a flutter app?

something like this:

class FirstCounter extends ChangeNotifier {
    int _i = 0;
    void increment() {
        i = i + 1;
        notifyListeners();
    }
}

class SecoundCounter extends ChangeNotifier {
    int _i = 0;
    void increment() {
        i = i + 1;
        notifyListeners();
    }

    void listen() {
        var resetCallback = () { i = 0;}
        FirstCounter.listen(resetCallback);
    }
}

I want SecoundCounter to reset when FirstCounter is updated.

2

Answers


  1. Chosen as BEST ANSWER
    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class Counter1 extends ChangeNotifier {
      int _counter = 0;
    
      int get counter {
        return _counter;
      }
    
      void increment() {
        _counter = _counter + 1;
        notifyListeners();
      }
    
      void reset() {
        _counter = 0;
        notifyListeners();
      }
    }
    
    class Counter2 extends ChangeNotifier {
      int _counter = 0;
    
      int get counter {
        return _counter;
      }
    
      void increment() {
        _counter = _counter + 1;
        notifyListeners();
      }
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            useMaterial3: true,
          ),
          home: MultiProvider(providers: [
            ChangeNotifierProvider(
              create: (context) {
                return Counter2();
              },
            ),
            ChangeNotifierProxyProvider<Counter2, Counter1>(
              create: (context) {
                return Counter1();
              },
              update: (BuildContext context, Counter2 value, Counter1? previous) {
                if (previous == null) {
                  throw StateError("Counter1 is null");
                }
                value.removeListener(previous.reset); // To avoid multiple listener
                value.addListener(previous.reset);
                return previous;
              },
            ),
          ], child: const MyHomePage()),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      const MyHomePage({super.key});
    
      @override
      Widget build(BuildContext context) {
        var counter1 = Provider.of<Counter1>(context);
        var counter2 = Provider.of<Counter2>(context);
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title:
                const Text("Let's try to reset counter 1 when counter 2 increment"),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'Counter 1:',
                ),
                Text(
                  '${counter1.counter}',
                  style: Theme.of(context).textTheme.headlineMedium,
                ),
                ElevatedButton(
                    onPressed: counter1.increment,
                    child: const Text("Increment counter 1")),
                const Text(
                  'Counter 2:',
                ),
                Text(
                  '${counter2.counter}',
                  style: Theme.of(context).textTheme.headlineMedium,
                ),
                ElevatedButton(
                    onPressed: counter2.increment,
                    child: const Text("Increment counter 2")),
              ],
            ),
          ),
        );
      }
    }
    
    

  2. use first.addListener(second.reset);

    import 'package:flutter/material.dart';
    
    class FirstCounter extends ChangeNotifier {
      int i = 0;
      void increment() {
        i = i + 1;
        notifyListeners();
      }
    }
    
    class SecondCounter extends ChangeNotifier {
      int i = 0;
    
      void increment() {
        i = i + 1;
        notifyListeners();
      }
    
      void reset() {
        i = 0;
        notifyListeners();
      }
    }
    
    class CounterWidget extends StatefulWidget {
      const CounterWidget({super.key});
    
      @override
      State<CounterWidget> createState() => _CounterWidgetState();
    }
    
    class _CounterWidgetState extends State<CounterWidget> {
      final FirstCounter first = FirstCounter();
      final SecondCounter second = SecondCounter();
      @override
      void initState() {
        super.initState();
        first.addListener(second.reset);
      }
    
      @override
      void dispose() {
        first.dispose();
        second.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return SizedBox(
          width: 200,
          child: Column(
            children: [
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  ListenableBuilder(
                      listenable: first,
                      builder: (context, child) {
                        return Text("${first.i}");
                      }),
                  TextButton(
                    onPressed: () {
                      first.increment();
                    },
                    child: Text("First"),
                  ),
                ],
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  ListenableBuilder(
                      listenable: second,
                      builder: (context, child) {
                        return Text("${second.i}");
                      }),
                  TextButton(
                    onPressed: () {
                      second.increment();
                    },
                    child: Text("Second"),
                  ),
                ],
              )
            ],
          ),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search