in Flutter Provider How to check when data received in consumer is updated

968

Solution 1

You can do this by 02 ways

  1. Using Selector() instead of Consumer().
  2. Using PuhserDataProvider() class.

1. Using Selector() instead of Consumer().

An equivalent to Consumer that can filter updates by selecting a limited amount of values and prevent rebuild if they don't change.


2. Using PuhserDataProvider() class.

Check your logic before calling notifyListers()

Here

class PuhserDataProvider extends ChangeNotifier {
  final Pusher pusher;
  Logger log = getLogger("PuhserDataProvider");


  //I changed _devicePusherData into _devicePusherDataGps
  //I dont know Data type of your .gps , so temperary i said it as Object , you need to change it
  Object _devicePusherDataGps;

  //I changed devicePusherData into devicePusherDataGps 
  //I dont know Data type of your .gps , so temperary i said it as Object , you need to change it
  Object get devicePusherDataGps => _devicePusherDataGps;

  //counter variable with default value 1 ,this will increment when each time value changed
  int counter = 1;

  PuhserDataProvider(String imei, String token, String pusherKey)
      : pusher = Pusher(
          pusherKey,
          PusherOptions(
              cluster: 'eu',
              authEndpoint: AUTH_URL,
              auth: PusherAuth(headers: {
                'Authorization': 'Bearer $token',
                'Content-Type': 'application/json',
                'Accept': 'application/json'
              })),
        ) {
    Channel channel = pusher.subscribe('private-$imei-send');

    channel.bind(
        'deviceevent',
        (data) =>
            _setDeviceData(DevicePusherData.fromJson(json.decode(data)[0])));
  }

  _setDeviceData(DevicePusherData devicePusherData) {
    if (_devicePusherDataGps == null) {
      _devicePusherDataGps = devicePusherData.gps;
    }
    else{
      if (devicePusherData.gps != _devicePusherDataGps) {
      //This will check value changes for 5 times.
        if (counter == 5) {
          counter = 1;
          this._devicePusherDataGps = devicePusherData.gps;
          notifyListeners();
        } else {
          counter++;
        }
      }
    }
    
  }

}

In above class, setter function was changed only to set gps value. Because in your question you said that you want to check Lat Lang value individually, So I create seperate setter method for it.


And Now in Consumer widget you need to change data.devicePusherData.gps into data.devicePusherDataGps

final lat = extractLat("${data.devicePusherDataGps}");
final lang = extractLang("${data.devicePusherDataGps}");

Hope this will help you. If you have any question on above, please comment I will try to help. (Sometimes code just have syntax errors, because I didnt have your json model class to import)

Solution 2

Your class should be looks like:

PusherDataProvider with ChangeNotifier {
  final Object _value;

  set value(Object value) {
    if (value != _value) {
      _value = value;
      // Notify listeners only when data changed
      notifyListeners();
    }

    Object get value => _value;
  }
}

So now yor Consumer's builder will be called when data is changed. Declare a counter variable which will be checked inside builder.

Share:
968
Javeed Ishaq
Author by

Javeed Ishaq

I am a passionate Software Developer, I love to build mobile apps. My expertise is Flutter, Android, Kotlin, Jetpack Compose, and Firebase.

Updated on December 26, 2022

Comments

  • Javeed Ishaq
    Javeed Ishaq over 1 year

    How can we check if data receiving in consumer via provider is updated or changed, I want to add a buffer to check the Lat Lang value before passing to google_maps_flutter, I want to check the value 5 times before passing to the google_maps_flutter widget to update the location

    Consumer<PuhserDataProvider>(builder: (context, data, child) {
              if (data.devicePusherData != null) {
                final lat = extractLat("${data.devicePusherData.gps}");
                final lang = extractLang("${data.devicePusherData.gps}");
    
                log.w(lat);
                log.w(lang);
    
                return GoogleMap(
                  onMapCreated: (GoogleMapController controller) {
                    _controller.complete(controller);
                  },
                  myLocationButtonEnabled: false,
                  initialCameraPosition: CameraPosition(
                    target: LatLng(lat, lang),
                    zoom: 16,
                  ),
                  markers: [
                    Marker(
                        markerId: MarkerId('0'),
                        position: LatLng(lat, lang),
                        onTap: () =>
                            setState(() => selectedPoint = LatLng(lat, lang)))
                  ].toSet(),
                  onTap: (point) => setState(() => selectedPoint = null),
                );
              } else {
                return Container(
                  height: MediaQuery.of(context).size.height * 0.8,
                  width: double.infinity,
                  child: Center(child: CircularProgressIndicator()),
                );
              }
            }),
    

    the provider used is a change notifier provider, Default constructer functions call the pusher to get values, the setter, and getter function to retrieve values.

        class PuhserDataProvider extends ChangeNotifier {
      final Pusher pusher;
      Logger log = getLogger("PuhserDataProvider");
      DevicePusherData _devicePusherData;
      DevicePusherData get devicePusherData => _devicePusherData;
    
      OBDPuhserData _obdPusherData;
      OBDPuhserData get obdPusherData => _obdPusherData;
    
      PuhserDataProvider(String imei, String token, String pusherKey)
          : pusher = Pusher(
              pusherKey,
              PusherOptions(
                  cluster: 'eu',
                  authEndpoint: AUTH_URL,
                  auth: PusherAuth(headers: {
                    'Authorization': 'Bearer $token',
                    'Content-Type': 'application/json',
                    'Accept': 'application/json'
                  })),
            ) {
        Channel channel = pusher.subscribe('private-$imei-send');
    
        channel.bind('obd-event',
            (data) => _setOBDData(OBDPuhserData.fromJson(json.decode(data)[0])));
    
        channel.bind(
            'deviceevent',
            (data) =>
                _setDeviceData(DevicePusherData.fromJson(json.decode(data)[0])));
      }
    
      _setDeviceData(DevicePusherData devicePusherData) {
        this._devicePusherData = devicePusherData;
        notifyListeners();
      }
    
      _setOBDData(OBDPuhserData obdPusherData) {
        this._obdPusherData = obdPusherData;
        notifyListeners();
      }
    }
    
    • dilshan
      dilshan over 3 years
      You can check value 5 times inside your PusherDataProvider class. After checking 5 times and if update or changed occurs then you can call notifyListeners() method.
    • dilshan
      dilshan over 3 years
      if you show the PusherDataProvider class, it helps to give better solution
    • Javeed Ishaq
      Javeed Ishaq over 3 years
      thanks, @TDM for your Kind comment, I have added the code for PusherDataProvider class
  • Javeed Ishaq
    Javeed Ishaq over 3 years
    Thanks, @BambinoUA I am looking into implementing code as per your instructions
  • Javeed Ishaq
    Javeed Ishaq over 3 years
    thanks TDM for you kind perfect answer :)