在 Flutter Provider 中如何检查消费者收到的数据何时更新

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

我们如何检查通过 providerconsumer 中接收的数据是否更新或更改,我想添加一个缓冲区以在传递给 [=15 之前检查 Lat Lang 值=],我想在传递给 google_maps_flutter 小部件以更新位置之前检查该值 5 次

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()),
            );
          }
        }),

使用的提供者是更改通知提供者,默认构造函数调用推送器来获取值,setter,getter 函数来检索值。

    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();
  }
}

你的 class 应该是这样的:

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;
  }
}

所以现在您的 Consumer 的构建器将在数据更改时被调用。声明一个将在构建器内部检查的计数器变量。

你可以通过02种方式做到这一点

  1. 使用 Selector() 而不是 Consumer()。
  2. 使用 PuhserDataProvider() class。

1.使用 Selector() 而不是 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。使用 PuhserDataProvider() class.

Check your logic before calling notifyListers()

这里

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++;
        }
      }
    }
    
  }

}

在上面的class中,setter函数只被更改为设置gps值。因为在你的问题中你说你想单独检查 Lat Lang 值,所以我为它创建了单独的 setter 方法。


现在在消费者小部件中,您需要将 data.devicePusherData.gps 更改为 data.devicePusherDataGps

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

希望这对您有所帮助。如果您对以上有任何疑问,请发表评论,我会尽力提供帮助。 (有时代码只是有语法错误,因为我没有要导入的 json 模型 class)