在 Flutter Provider 中如何检查消费者收到的数据何时更新
in Flutter Provider How to check when data received in consumer is updated
我们如何检查通过 provider
在 consumer
中接收的数据是否更新或更改,我想添加一个缓冲区以在传递给 [=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种方式做到这一点
- 使用 Selector() 而不是 Consumer()。
- 使用 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)
我们如何检查通过 provider
在 consumer
中接收的数据是否更新或更改,我想添加一个缓冲区以在传递给 [=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种方式做到这一点
- 使用 Selector() 而不是 Consumer()。
- 使用 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)