Search code examples
flutterflutter-provider

How to listen to a class change on Flutter's BuildContext.select()?


I am very new to Flutter, and have been trying to use the Provider package to handle state management. Is is possible to listen to changes on a whole class with context.select()?

The simplified code is below. I know the values are changing under the hood, but are not being reflected in the UI.

I also know that if I listen to each individual value on the class, it will reflect. But I was hopping for a way to get the change on the class as a whole.

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final WageValues wageValues = context.select<ValuesModel, WageValues>(
      (values) => values.wageValues,
    );

    return Column(
      children: [
        Text('Wage: ${roundToDecimals(wageValues.wage)}'),
        Text('Insurance Percent: ${wageValues.insurancePercent}'),
        Text('Insurance Sum: ${roundToDecimals(wageValues.insuranceSum)}'),
        Text('Wage Total: ${roundToDecimals(wageValues.wageTotal)}'),
        const WageForm(),
      ],
    );
  }
}
class WageValues {
  double wage = 12;
  int insurancePercent = 30;

  double get insuranceSum => wage * insurancePercent * 0.01;
  double get wageTotal => wage + insuranceSum;
}

class ValuesModel extends ChangeNotifier {
  final WageValues _wageValues = WageValues();

  WageValues get wageValues => _wageValues;

  void setWage(double wage) {
    _wageValues.wage = wage;
    notifyListeners();
  }

  void setInsurancePercent(int insurancePercent) {
    _wageValues.insurancePercent = insurancePercent;
    notifyListeners();
  }
}

Solution

  • I'm using Get package instead of Provider package for this code:

    home_page.dart

    import 'dart:math';
    
    import 'package:flutter/material.dart';
    import 'package:get/get.dart';
    import 'package:getx_obs_class/src/controllers/checker_controller.dart';
    
    class HomePage extends StatelessWidget {
      /* ---------------------------------------------------------------------------- */
      const HomePage({Key key}) : super(key: key);
      /* ---------------------------------------------------------------------------- */
      @override
      Widget build(BuildContext context) {
        var _rnd = Random();
        final _wv = valuesModel.wageValues;
    
        return Scaffold(
          body: SafeArea(
            child: Padding(
              padding: const EdgeInsets.all(10),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Obx(() => Text('Wage: ${_wv.wage.toStringAsFixed(2)}')),
                  Obx(() => Text('Insurance Percent: ${_wv.insurancePercent}%')),
                  Obx(() => Text('Insurance Sum: ${_wv.insuranceSum.toStringAsFixed(2)}')),
                  Obx(() => Text('Wage Total: ${_wv.wageTotal.toStringAsFixed(2)}')),
                ],
              ),
            ),
          ),
          floatingActionButton: FloatingActionButton(
            child: Icon(Icons.track_changes),
            onPressed: () {
              valuesModel
              ..setWage(_rnd.nextDouble() * 100)
              ..setInsurancePercent(_rnd.nextInt(100));
              print('\$${_wv.wage} : ${_wv.insurancePercent}%');
            },
          ),
        );
      }
    }
    

    checker_controller.dart

    import 'package:get/get.dart';
    
    
    class WageValues extends GetxController {
      var wage = 12.0.obs;
      var insurancePercent = 30.obs;
    
      double get insuranceSum => wage * insurancePercent.value * 0.01;
      double get wageTotal => wage.value + insuranceSum;
    }
    
    class ValuesModel {
      final WageValues _wageValues = Get.put(WageValues());
    
      WageValues get wageValues => _wageValues;
    
      void setWage(double wage) => _wageValues.wage.value = wage;
      void setInsurancePercent(int insurancePercent) => _wageValues.insurancePercent.value = insurancePercent;
    }
    
    
    final valuesModel = ValuesModel();