I’m using google_maps_flutter
, flutter_polyline_points
and firebase_database
packages in my Flutter project.
I have another app which is for driver and it’s live location is shared with firebase realtime database and I watch the location changes in this app.
Everything is ok, except, when location update the map is jamping not moving smoothly.
here is my code:
This is map widget and streamBuilder where I watch location changes
Widget build(BuildContext context) {
var mover = Provider.of<TrackingProvider>(context, listen: false).mover;
var orderId = Provider.of<TrackingProvider>(context, listen: false).orderId;
return Scaffold(
body: StreamBuilder(
stream: db.ref("mover_${mover['user']['id']}_$orderId").onValue,
builder: (context, AsyncSnapshot snapshot) {
Map<dynamic, dynamic>? newLocation;
// Cancel the previous debounce operation if it exists
_debounceOperation?.cancel();
if (snapshot.hasData) {
if ((snapshot.data as DatabaseEvent).snapshot.value != null) {
newLocation = (snapshot.data as DatabaseEvent).snapshot.value as Map;
_moverLatLng =
LatLng(newLocation['latitude'], newLocation['longitude']);
_updateMoverMarker(context, newLocation);
_debounceOperation = CancelableOperation.fromFuture(
_updateMoverPolyline(context, newLocation),
onCancel: () => debugPrint('Debounce operation canceled.'),
);
_watchMoverLocation(context, newLocation);
}
}
return Stack(
children: [
SizedBox(
height: MediaQuery.of(context).size.height *
(isTablet(context) ? 0.92 : 0.88),
child: GoogleMap(
mapType: MapType.normal,
initialCameraPosition: CameraPosition(
target: LatLng(49.28365819800792, -123.10308363551924),
zoom: 13.4746,
),
myLocationEnabled: false,
myLocationButtonEnabled: false,
tiltGesturesEnabled: true,
mapToolbarEnabled: false,
compassEnabled: false,
scrollGesturesEnabled: true,
zoomGesturesEnabled: true,
zoomControlsEnabled: false,
markers: Set<Marker>.of(markers.values),
polylines: Set<Polyline>.of(polylines.values),
onMapCreated: (GoogleMapController controller) async {
_mapController = controller;
pickupIcon = await getPickupMarker(context);
destIcon = await getDestinationMarker(context);
await _initMarkers();
await _getPolyline(_pickupAddress);
List<LatLng> list = [
LatLng(_pickupLat!, _pickupLng!),
LatLng(_destLat!, _destLng!)
];
_setBounds(list);
},
onTap: (LatLng latLng) {
//_setBounds();
},
),
),
MapButtons(),
mapBottomBar(context, newLocation, mover),
],
);
},
),
);
}
Here I clear plylines and update the bounds
_watchMoverLocation(context, newLocation) async {
if (newLocation.isNotEmpty) {
polylineCoordinates.clear();
if (newLocation['status'] == "toPickup") {
List<LatLng> list = [_moverLatLng, LatLng(_pickupLat!, _pickupLng!)];
_setBounds(list);
}
if (newLocation['status'] == "toDestination") {
List<LatLng> list = [_moverLatLng, LatLng(_destLat!, _destLng!)];
_setBounds(list);
}
}
}
Here I update the marker
void _updateMoverMarker(context, locationData) async {
if (locationData != null) {
Uint8List? customMarker =
Provider.of<TrackingProvider>(context, listen: false).moverMarker;
MarkerId markerId = MarkerId("Mover");
final latLng =
LatLng(locationData['latitude'], locationData['longitude']);
final animation =
_moverLatLng != const LatLng(0.0, 0.0) && _moverLatLng != latLng
? Tween(begin: _moverLatLng, end: latLng)
.animate(_animationController)
: ConstantTween<LatLng>(latLng).animate(_animationController);
_moverLatLng = latLng;
_mapController?.animateCamera(CameraUpdate.newLatLng(_moverLatLng));
_animationController.reset();
_animationController.forward();
_animationController.addListener(() {
Marker marker = Marker(
markerId: markerId,
position: animation.value,
zIndex: 2,
icon: BitmapDescriptor.fromBytes(customMarker!),
infoWindow:
InfoWindow(title: "Mover", snippet: "${locationData['name']}"),
);
markers[markerId] = marker;
});
}
}
And this function update polyline
Future<PolylineResult> _updateMoverPolyline(context, moverLocation) async {
String address;
double latitude, longitude;
if (moverLocation['status'] == "toDestination") {
address = _destAddress!;
latitude = _destLat!;
longitude = _destLng!;
} else {
address = _pickupAddress!;
latitude = _pickupLat!;
longitude = _pickupLng!;
}
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
mapKey,
PointLatLng(moverLocation['latitude'], moverLocation['longitude']),
PointLatLng(latitude, longitude),
travelMode: TravelMode.driving,
wayPoints: [PolylineWayPoint(location: "$address")],
);
var pts = [];
if (result.points.isNotEmpty) {
moverPolylineCoordinates = [];
moverPolylineCoordinates.clear();
result.points.forEach((PointLatLng point) {
pts.add(point);
moverPolylineCoordinates.add(LatLng(point.latitude, point.longitude));
});
}
_addMoverPolyLine();
return result;
}
Please correct me if I’m doing anything wrong