strato_cruiser
strato_cruiser

Reputation: 23

How to use Flutter Riverpod to act like a ChangeNotifierProxy Provider?

just wondering if there is any way to use the Riverpod Package in a way, that it works like the ChangeNotifierProxy Provider. I have made this simple code where the "MySecondClass" shall be updated when 'MyFirstClass" changes its properties. In the 'MySecondClass' is a method which uses the data/variable from 'MyFirstClass' when it has changed.

So far, when I press the button and the onPressed function is executed, 'MySecondClass' is updated once, but stays than the same even if I push the button again.

This is the part with the provider and classes:

    void main() {
  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}

final firstClassProvider = ChangeNotifierProvider((ref) => MyFirstClass());

final secondClassProvider = ChangeNotifierProvider<MySecondClass>(
    (ref) => MySecondClass(MyFirstClass().myFirstNumber));

class MyApp extends ConsumerWidget {
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final firstClassNotifier = watch(firstClassProvider);
    final secondClassNotifier = watch(secondClassProvider);

    return MaterialApp(...


class MyFirstClass extends ChangeNotifier {
  int _myFirstNumber = 10;

  void increaseMyFirstNumber() {
    _myFirstNumber = _myFirstNumber + 1;
    notifyListeners();
  }

  get myFirstNumber => _myFirstNumber;
}

class MySecondClass extends ChangeNotifier {
  MySecondClass(this.data);
  final int data;

  int _mySecondNumber = 2;

  void receiveNumberFromClass1() {
    _mySecondNumber = data;
    print('$data Data');
    notifyListeners();
  }

  get mySecondNumber => _mySecondNumber;
}

And If you want to copy the whole code for this example, here it is:

   import 'package:flutter/material.dart';
import 'package:flutter_riverpod/all.dart';
import 'package:riverpod/riverpod.dart';
import 'package:riverpod/all.dart';

void main() {
  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}

final firstClassProvider = ChangeNotifierProvider((ref) => MyFirstClass());

final secondClassProvider = ChangeNotifierProvider<MySecondClass>(
    (ref) => MySecondClass(MyFirstClass().myFirstNumber));

class MyApp extends ConsumerWidget {
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final firstClassNotifier = watch(firstClassProvider);
    final secondClassNotifier = watch(secondClassProvider);

    return MaterialApp(
      home: Scaffold(
        body: Container(
          color: Colors.blueGrey,
          alignment: Alignment.center,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Text(
                firstClassNotifier._myFirstNumber.toString(),
                style: TextStyle(fontSize: 40),
              ),
              Text(secondClassNotifier.mySecondNumber.toString()),
              MaterialButton(
                  child: Container(
                    height: 50,
                    width: 50,
                    color: Colors.deepOrangeAccent,
                  ),
                  onPressed: () {
                    firstClassNotifier.increaseMyFirstNumber();
                    secondClassNotifier.receiveNumberFromClass1();
                  }),
            ],
          ),
        ),
      ),
    );
  }
}

class MyFirstClass extends ChangeNotifier {
  int _myFirstNumber = 10;

  void increaseMyFirstNumber() {
    _myFirstNumber = _myFirstNumber + 1;
    notifyListeners();
  }

  get myFirstNumber => _myFirstNumber;
}

class MySecondClass extends ChangeNotifier {
  MySecondClass(this.data);
  final int data;

  int _mySecondNumber = 2;

  void receiveNumberFromClass1() {
    _mySecondNumber = data;
    print('$data Data');
    notifyListeners();
  }

  get mySecondNumber => _mySecondNumber;
}

Upvotes: 0

Views: 1281

Answers (2)

Kalex
Kalex

Reputation: 356

You can use the (ref) that is passed in Riverpod providers constructor to obtain other providers in a nested fashion, similar to what ChangeNotifierProxyProvider permits.

final provider = Provider((ref) {
  final repository = ref.watch(repositoryProvider);  // use ref to obtain other providers
  return SomeValue(repository);
})

Source: official Riverpod documentation

Upvotes: 0

strato_cruiser
strato_cruiser

Reputation: 23

After doing some research and testing, I found a way. Not sure if it is the way you should do it. But so far it works fine. Thats the code I added:

final firstClassProvider = ChangeNotifierProvider((ref) => MyFirstClass());

final secondClassProvider = ChangeNotifierProvider<MySecondClass>((ref) {
  final secondClass = MySecondClass(MyFirstClass().myFirstNumber);
  return secondClass;
});


class MySecondClass extends ChangeNotifier {
  MySecondClass(this.data);
  final int data;

  int _mySecondNumber = 2;
  int _myOtherNumber = 8;

  void updateClass2(number) {
    _myOtherNumber = number;
    print('$_myOtherNumber other Number');
  }

  void receiveNumberFromClass1() {
    _mySecondNumber = _myOtherNumber;
    print('$data Data');
    notifyListeners();
  }

  get mySecondNumber => _mySecondNumber;
}

Upvotes: 1

Related Questions