1
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")),
          ],
        ),
      ),
    );
  }
}

1 Answer 1

0

To simplify the code, you can remove the manual adding and removing of listeners by using context.watch, which automatically listens for changes.

Here is my proposition:

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

class Counter1 extends ChangeNotifier {
  int _counter = 0;

  int get counter => _counter;

  void increment() {
    _counter = _counter + 1;
    notifyListeners();
  }

  void reset() {
    _counter = 0;
    notifyListeners();
  }
}

class Counter2 extends ChangeNotifier {
  int _counter = 0;

  int get counter => _counter;

  void increment() {
    _counter = _counter + 1;
    notifyListeners();
  }
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => Counter2()),
        ChangeNotifierProxyProvider<Counter2, Counter1>(
          create: (_) => Counter1(),
          update: (context, counter2, counter1) {
            if (counter1 == null) throw ArgumentError.notNull('counter1');
            return counter1;
          },
        ),
      ],
      child: MaterialApp(
        home: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter1 = context.watch<Counter1>();
    final counter2 = context.watch<Counter2>();

    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>[
            Text('Counter 1: ${counter1.counter}',
                style: const TextStyle(fontSize: 20)),
            Text('Counter 2: ${counter2.counter}',
                style: const TextStyle(fontSize: 20)),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                counter1.increment();
              },
              child: const Text('Increment Counter 1'),
            ),
            ElevatedButton(
              onPressed: () {
                counter1.reset();
                counter2.increment();
              },
              child: const Text('Increment Counter 2'),
            ),
          ],
        ),
      ),
    );
  }
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.