в провайдере Flutter Как проверить, когда данные, полученные от потребителя, обновляются

Как мы можем проверить, обновлены или изменены данные, получаемые в consumer через provider, я хочу добавить буфер для проверки значения Lat Lang перед переходом к google_maps_flutter, я хочу проверить значение 5 раз перед переходом к виджету google_maps_flutter для обновления местоположения

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

используемый поставщик - это поставщик уведомлений об изменениях, функции конструктора по умолчанию вызывают толкатель для получения значений, метод установки и функцию получения для получения значений.

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

person Javeed Ishaq    schedule 19.12.2020    source источник
comment
Вы можете проверить значение 5 раз в своем классе PusherDataProvider. После проверки 5 раз и в случае обновления или изменения вы можете вызвать метод notifyListeners ().   -  person TDM    schedule 19.12.2020
comment
если вы покажете класс PusherDataProvider, это поможет дать лучшее решение   -  person TDM    schedule 19.12.2020
comment
спасибо, @TDM за добрый комментарий, я добавил код для класса PusherDataProvider   -  person Javeed Ishaq    schedule 19.12.2020


Ответы (2)


Это можно сделать двумя способами

  1. Использование Selector () вместо Consumer ().
  2. Использование класса PuhserDataProvider ().

1. Использование Selector () вместо Consumer ().

Эквивалент Consumer, который может фильтровать обновления, выбирая ограниченное количество значений, и предотвращать перестроение, если они не меняются.


2. Использование PuhserDataProvider () класса.

Проверьте свою логику перед вызовом 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++;
        }
      }
    }
    
  }

}

В приведенном выше классе функция установки была изменена только для установки значения gps. Потому что в своем вопросе вы сказали, что хотите проверять значение Lat Lang индивидуально, поэтому я создаю для него отдельный метод установки.


А теперь в виджете Consumer вам нужно заменить data.devicePusherData.gps на data.devicePusherDataGps

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

Надеюсь, что это поможет вам. Если у вас есть какие-либо вопросы по вышеизложенному, прокомментируйте, я постараюсь помочь. (Иногда в коде просто синтаксические ошибки, потому что у меня не было вашего класса модели json для импорта)

person TDM    schedule 19.12.2020
comment
спасибо TDM за добрый прекрасный ответ :) - person Javeed Ishaq; 21.12.2020

Ваш класс должен выглядеть так:

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 будет вызываться при изменении данных. Объявите переменную счетчика, которая будет проверяться внутри построителя.

person BambinoUA    schedule 19.12.2020
comment
Спасибо, @BambinoUA. Я пытаюсь реализовать код в соответствии с вашими инструкциями. - person Javeed Ishaq; 19.12.2020