mirror of
https://github.com/flutter/packages.git
synced 2025-06-29 06:06:59 +08:00
[google_maps_flutter] Fix async handling in examples (#4729)
Applies the fixes from https://github.com/flutter/packages/pull/4171 to the minimal ExampleGoogleMaps class used in the Android and iOS implementation package examples, as they had the same issue. Also sets up unit testing of the examples in order to add testing of this fix. The fake is copied directly from the app-facing package, and the unit tests are slightly modified versions of the tests in the app-facing package as well.
This commit is contained in:
@ -0,0 +1 @@
|
||||
maps.key=SomeKeyHere
|
@ -420,41 +420,41 @@ class _ExampleGoogleMapState extends State<ExampleGoogleMap> {
|
||||
return;
|
||||
}
|
||||
final ExampleGoogleMapController controller = await _controller.future;
|
||||
await controller._updateMapConfiguration(updates);
|
||||
unawaited(controller._updateMapConfiguration(updates));
|
||||
_mapConfiguration = newConfig;
|
||||
}
|
||||
|
||||
Future<void> _updateMarkers() async {
|
||||
final ExampleGoogleMapController controller = await _controller.future;
|
||||
await controller._updateMarkers(
|
||||
MarkerUpdates.from(_markers.values.toSet(), widget.markers));
|
||||
unawaited(controller._updateMarkers(
|
||||
MarkerUpdates.from(_markers.values.toSet(), widget.markers)));
|
||||
_markers = keyByMarkerId(widget.markers);
|
||||
}
|
||||
|
||||
Future<void> _updatePolygons() async {
|
||||
final ExampleGoogleMapController controller = await _controller.future;
|
||||
await controller._updatePolygons(
|
||||
PolygonUpdates.from(_polygons.values.toSet(), widget.polygons));
|
||||
unawaited(controller._updatePolygons(
|
||||
PolygonUpdates.from(_polygons.values.toSet(), widget.polygons)));
|
||||
_polygons = keyByPolygonId(widget.polygons);
|
||||
}
|
||||
|
||||
Future<void> _updatePolylines() async {
|
||||
final ExampleGoogleMapController controller = await _controller.future;
|
||||
await controller._updatePolylines(
|
||||
PolylineUpdates.from(_polylines.values.toSet(), widget.polylines));
|
||||
unawaited(controller._updatePolylines(
|
||||
PolylineUpdates.from(_polylines.values.toSet(), widget.polylines)));
|
||||
_polylines = keyByPolylineId(widget.polylines);
|
||||
}
|
||||
|
||||
Future<void> _updateCircles() async {
|
||||
final ExampleGoogleMapController controller = await _controller.future;
|
||||
await controller._updateCircles(
|
||||
CircleUpdates.from(_circles.values.toSet(), widget.circles));
|
||||
unawaited(controller._updateCircles(
|
||||
CircleUpdates.from(_circles.values.toSet(), widget.circles)));
|
||||
_circles = keyByCircleId(widget.circles);
|
||||
}
|
||||
|
||||
Future<void> _updateTileOverlays() async {
|
||||
final ExampleGoogleMapController controller = await _controller.future;
|
||||
await controller._updateTileOverlays(widget.tileOverlays);
|
||||
unawaited(controller._updateTileOverlays(widget.tileOverlays));
|
||||
}
|
||||
|
||||
Future<void> onPlatformViewCreated(int id) async {
|
||||
|
@ -27,6 +27,7 @@ dev_dependencies:
|
||||
sdk: flutter
|
||||
integration_test:
|
||||
sdk: flutter
|
||||
stream_transform: ^2.0.0
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
@ -0,0 +1,175 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:google_maps_flutter_example/example_google_map.dart';
|
||||
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
|
||||
|
||||
import 'fake_google_maps_flutter_platform.dart';
|
||||
|
||||
Widget _mapWithObjects({
|
||||
Set<Circle> circles = const <Circle>{},
|
||||
Set<Marker> markers = const <Marker>{},
|
||||
Set<Polygon> polygons = const <Polygon>{},
|
||||
Set<Polyline> polylines = const <Polyline>{},
|
||||
Set<TileOverlay> tileOverlays = const <TileOverlay>{},
|
||||
}) {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: ExampleGoogleMap(
|
||||
initialCameraPosition: const CameraPosition(target: LatLng(10.0, 15.0)),
|
||||
circles: circles,
|
||||
markers: markers,
|
||||
polygons: polygons,
|
||||
polylines: polylines,
|
||||
tileOverlays: tileOverlays,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void main() {
|
||||
late FakeGoogleMapsFlutterPlatform platform;
|
||||
|
||||
setUp(() {
|
||||
platform = FakeGoogleMapsFlutterPlatform();
|
||||
GoogleMapsFlutterPlatform.instance = platform;
|
||||
});
|
||||
|
||||
testWidgets('circle updates with delays', (WidgetTester tester) async {
|
||||
platform.simulatePlatformDelay = true;
|
||||
|
||||
const Circle c1 = Circle(circleId: CircleId('circle_1'));
|
||||
const Circle c2 = Circle(circleId: CircleId('circle_2'));
|
||||
const Circle c3 = Circle(circleId: CircleId('circle_3'), radius: 1);
|
||||
const Circle c3updated = Circle(circleId: CircleId('circle_3'), radius: 10);
|
||||
|
||||
// First remove one and add another, then update the new one.
|
||||
await tester.pumpWidget(_mapWithObjects(circles: <Circle>{c1, c2}));
|
||||
await tester.pumpWidget(_mapWithObjects(circles: <Circle>{c1, c3}));
|
||||
await tester.pumpWidget(_mapWithObjects(circles: <Circle>{c1, c3updated}));
|
||||
|
||||
final PlatformMapStateRecorder map = platform.lastCreatedMap;
|
||||
|
||||
expect(map.circleUpdates.length, 3);
|
||||
|
||||
expect(map.circleUpdates[0].circlesToChange.isEmpty, true);
|
||||
expect(map.circleUpdates[0].circlesToAdd, <Circle>{c1, c2});
|
||||
expect(map.circleUpdates[0].circleIdsToRemove.isEmpty, true);
|
||||
|
||||
expect(map.circleUpdates[1].circlesToChange.isEmpty, true);
|
||||
expect(map.circleUpdates[1].circlesToAdd, <Circle>{c3});
|
||||
expect(map.circleUpdates[1].circleIdsToRemove, <CircleId>{c2.circleId});
|
||||
|
||||
expect(map.circleUpdates[2].circlesToChange, <Circle>{c3updated});
|
||||
expect(map.circleUpdates[2].circlesToAdd.isEmpty, true);
|
||||
expect(map.circleUpdates[2].circleIdsToRemove.isEmpty, true);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
});
|
||||
|
||||
testWidgets('marker updates with delays', (WidgetTester tester) async {
|
||||
platform.simulatePlatformDelay = true;
|
||||
|
||||
const Marker m1 = Marker(markerId: MarkerId('marker_1'));
|
||||
const Marker m2 = Marker(markerId: MarkerId('marker_2'));
|
||||
const Marker m3 = Marker(markerId: MarkerId('marker_3'));
|
||||
const Marker m3updated =
|
||||
Marker(markerId: MarkerId('marker_3'), draggable: true);
|
||||
|
||||
// First remove one and add another, then update the new one.
|
||||
await tester.pumpWidget(_mapWithObjects(markers: <Marker>{m1, m2}));
|
||||
await tester.pumpWidget(_mapWithObjects(markers: <Marker>{m1, m3}));
|
||||
await tester.pumpWidget(_mapWithObjects(markers: <Marker>{m1, m3updated}));
|
||||
|
||||
final PlatformMapStateRecorder map = platform.lastCreatedMap;
|
||||
|
||||
expect(map.markerUpdates.length, 3);
|
||||
|
||||
expect(map.markerUpdates[0].markersToChange.isEmpty, true);
|
||||
expect(map.markerUpdates[0].markersToAdd, <Marker>{m1, m2});
|
||||
expect(map.markerUpdates[0].markerIdsToRemove.isEmpty, true);
|
||||
|
||||
expect(map.markerUpdates[1].markersToChange.isEmpty, true);
|
||||
expect(map.markerUpdates[1].markersToAdd, <Marker>{m3});
|
||||
expect(map.markerUpdates[1].markerIdsToRemove, <MarkerId>{m2.markerId});
|
||||
|
||||
expect(map.markerUpdates[2].markersToChange, <Marker>{m3updated});
|
||||
expect(map.markerUpdates[2].markersToAdd.isEmpty, true);
|
||||
expect(map.markerUpdates[2].markerIdsToRemove.isEmpty, true);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
});
|
||||
|
||||
testWidgets('polygon updates with delays', (WidgetTester tester) async {
|
||||
platform.simulatePlatformDelay = true;
|
||||
|
||||
const Polygon p1 = Polygon(polygonId: PolygonId('polygon_1'));
|
||||
const Polygon p2 = Polygon(polygonId: PolygonId('polygon_2'));
|
||||
const Polygon p3 =
|
||||
Polygon(polygonId: PolygonId('polygon_3'), strokeWidth: 1);
|
||||
const Polygon p3updated =
|
||||
Polygon(polygonId: PolygonId('polygon_3'), strokeWidth: 2);
|
||||
|
||||
// First remove one and add another, then update the new one.
|
||||
await tester.pumpWidget(_mapWithObjects(polygons: <Polygon>{p1, p2}));
|
||||
await tester.pumpWidget(_mapWithObjects(polygons: <Polygon>{p1, p3}));
|
||||
await tester
|
||||
.pumpWidget(_mapWithObjects(polygons: <Polygon>{p1, p3updated}));
|
||||
|
||||
final PlatformMapStateRecorder map = platform.lastCreatedMap;
|
||||
|
||||
expect(map.polygonUpdates.length, 3);
|
||||
|
||||
expect(map.polygonUpdates[0].polygonsToChange.isEmpty, true);
|
||||
expect(map.polygonUpdates[0].polygonsToAdd, <Polygon>{p1, p2});
|
||||
expect(map.polygonUpdates[0].polygonIdsToRemove.isEmpty, true);
|
||||
|
||||
expect(map.polygonUpdates[1].polygonsToChange.isEmpty, true);
|
||||
expect(map.polygonUpdates[1].polygonsToAdd, <Polygon>{p3});
|
||||
expect(map.polygonUpdates[1].polygonIdsToRemove, <PolygonId>{p2.polygonId});
|
||||
|
||||
expect(map.polygonUpdates[2].polygonsToChange, <Polygon>{p3updated});
|
||||
expect(map.polygonUpdates[2].polygonsToAdd.isEmpty, true);
|
||||
expect(map.polygonUpdates[2].polygonIdsToRemove.isEmpty, true);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
});
|
||||
|
||||
testWidgets('polyline updates with delays', (WidgetTester tester) async {
|
||||
platform.simulatePlatformDelay = true;
|
||||
|
||||
const Polyline p1 = Polyline(polylineId: PolylineId('polyline_1'));
|
||||
const Polyline p2 = Polyline(polylineId: PolylineId('polyline_2'));
|
||||
const Polyline p3 =
|
||||
Polyline(polylineId: PolylineId('polyline_3'), width: 1);
|
||||
const Polyline p3updated =
|
||||
Polyline(polylineId: PolylineId('polyline_3'), width: 2);
|
||||
|
||||
// First remove one and add another, then update the new one.
|
||||
await tester.pumpWidget(_mapWithObjects(polylines: <Polyline>{p1, p2}));
|
||||
await tester.pumpWidget(_mapWithObjects(polylines: <Polyline>{p1, p3}));
|
||||
await tester
|
||||
.pumpWidget(_mapWithObjects(polylines: <Polyline>{p1, p3updated}));
|
||||
|
||||
final PlatformMapStateRecorder map = platform.lastCreatedMap;
|
||||
|
||||
expect(map.polylineUpdates.length, 3);
|
||||
|
||||
expect(map.polylineUpdates[0].polylinesToChange.isEmpty, true);
|
||||
expect(map.polylineUpdates[0].polylinesToAdd, <Polyline>{p1, p2});
|
||||
expect(map.polylineUpdates[0].polylineIdsToRemove.isEmpty, true);
|
||||
|
||||
expect(map.polylineUpdates[1].polylinesToChange.isEmpty, true);
|
||||
expect(map.polylineUpdates[1].polylinesToAdd, <Polyline>{p3});
|
||||
expect(map.polylineUpdates[1].polylineIdsToRemove,
|
||||
<PolylineId>{p2.polylineId});
|
||||
|
||||
expect(map.polylineUpdates[2].polylinesToChange, <Polyline>{p3updated});
|
||||
expect(map.polylineUpdates[2].polylinesToAdd.isEmpty, true);
|
||||
expect(map.polylineUpdates[2].polylineIdsToRemove.isEmpty, true);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
});
|
||||
}
|
@ -0,0 +1,303 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
|
||||
import 'package:stream_transform/stream_transform.dart';
|
||||
|
||||
// A dummy implementation of the platform interface for tests.
|
||||
class FakeGoogleMapsFlutterPlatform extends GoogleMapsFlutterPlatform {
|
||||
FakeGoogleMapsFlutterPlatform();
|
||||
|
||||
/// The IDs passed to each call to buildView, in call order.
|
||||
List<int> createdIds = <int>[];
|
||||
|
||||
/// A map of creation IDs to fake map instances.
|
||||
Map<int, PlatformMapStateRecorder> mapInstances =
|
||||
<int, PlatformMapStateRecorder>{};
|
||||
|
||||
PlatformMapStateRecorder get lastCreatedMap => mapInstances[createdIds.last]!;
|
||||
|
||||
/// Whether to add a small delay to async calls to simulate more realistic
|
||||
/// async behavior (simulating the platform channel calls most
|
||||
/// implementations will do).
|
||||
///
|
||||
/// When true, requires tests to `pumpAndSettle` at the end of the test
|
||||
/// to avoid exceptions.
|
||||
bool simulatePlatformDelay = false;
|
||||
|
||||
/// Whether `dispose` has been called.
|
||||
bool disposed = false;
|
||||
|
||||
/// Stream controller to inject events for testing.
|
||||
final StreamController<MapEvent<dynamic>> mapEventStreamController =
|
||||
StreamController<MapEvent<dynamic>>.broadcast();
|
||||
|
||||
@override
|
||||
Future<void> init(int mapId) async {}
|
||||
|
||||
@override
|
||||
Future<void> updateMapConfiguration(
|
||||
MapConfiguration update, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
mapInstances[mapId]?.mapConfiguration = update;
|
||||
await _fakeDelay();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateMarkers(
|
||||
MarkerUpdates markerUpdates, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
mapInstances[mapId]?.markerUpdates.add(markerUpdates);
|
||||
await _fakeDelay();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updatePolygons(
|
||||
PolygonUpdates polygonUpdates, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
mapInstances[mapId]?.polygonUpdates.add(polygonUpdates);
|
||||
await _fakeDelay();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updatePolylines(
|
||||
PolylineUpdates polylineUpdates, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
mapInstances[mapId]?.polylineUpdates.add(polylineUpdates);
|
||||
await _fakeDelay();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateCircles(
|
||||
CircleUpdates circleUpdates, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
mapInstances[mapId]?.circleUpdates.add(circleUpdates);
|
||||
await _fakeDelay();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateTileOverlays({
|
||||
required Set<TileOverlay> newTileOverlays,
|
||||
required int mapId,
|
||||
}) async {
|
||||
mapInstances[mapId]?.tileOverlaySets.add(newTileOverlays);
|
||||
await _fakeDelay();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clearTileCache(
|
||||
TileOverlayId tileOverlayId, {
|
||||
required int mapId,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<void> animateCamera(
|
||||
CameraUpdate cameraUpdate, {
|
||||
required int mapId,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<void> moveCamera(
|
||||
CameraUpdate cameraUpdate, {
|
||||
required int mapId,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<void> setMapStyle(
|
||||
String? mapStyle, {
|
||||
required int mapId,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<LatLngBounds> getVisibleRegion({
|
||||
required int mapId,
|
||||
}) async {
|
||||
return LatLngBounds(
|
||||
southwest: const LatLng(0, 0), northeast: const LatLng(0, 0));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ScreenCoordinate> getScreenCoordinate(
|
||||
LatLng latLng, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
return const ScreenCoordinate(x: 0, y: 0);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LatLng> getLatLng(
|
||||
ScreenCoordinate screenCoordinate, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
return const LatLng(0, 0);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> showMarkerInfoWindow(
|
||||
MarkerId markerId, {
|
||||
required int mapId,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<void> hideMarkerInfoWindow(
|
||||
MarkerId markerId, {
|
||||
required int mapId,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<bool> isMarkerInfoWindowShown(
|
||||
MarkerId markerId, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<double> getZoomLevel({
|
||||
required int mapId,
|
||||
}) async {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List?> takeSnapshot({
|
||||
required int mapId,
|
||||
}) async {
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<CameraMoveStartedEvent> onCameraMoveStarted({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<CameraMoveStartedEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<CameraMoveEvent> onCameraMove({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<CameraMoveEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<CameraIdleEvent> onCameraIdle({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<CameraIdleEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<MarkerTapEvent> onMarkerTap({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<MarkerTapEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<InfoWindowTapEvent> onInfoWindowTap({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<InfoWindowTapEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<MarkerDragStartEvent> onMarkerDragStart({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<MarkerDragStartEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<MarkerDragEvent> onMarkerDrag({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<MarkerDragEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<MarkerDragEndEvent> onMarkerDragEnd({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<MarkerDragEndEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<PolylineTapEvent> onPolylineTap({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<PolylineTapEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<PolygonTapEvent> onPolygonTap({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<PolygonTapEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<CircleTapEvent> onCircleTap({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<CircleTapEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<MapTapEvent> onTap({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<MapTapEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<MapLongPressEvent> onLongPress({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<MapLongPressEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose({required int mapId}) {
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildViewWithConfiguration(
|
||||
int creationId,
|
||||
PlatformViewCreatedCallback onPlatformViewCreated, {
|
||||
required MapWidgetConfiguration widgetConfiguration,
|
||||
MapObjects mapObjects = const MapObjects(),
|
||||
MapConfiguration mapConfiguration = const MapConfiguration(),
|
||||
}) {
|
||||
final PlatformMapStateRecorder? instance = mapInstances[creationId];
|
||||
if (instance == null) {
|
||||
createdIds.add(creationId);
|
||||
mapInstances[creationId] = PlatformMapStateRecorder(
|
||||
widgetConfiguration: widgetConfiguration,
|
||||
mapConfiguration: mapConfiguration,
|
||||
mapObjects: mapObjects);
|
||||
onPlatformViewCreated(creationId);
|
||||
}
|
||||
return Container();
|
||||
}
|
||||
|
||||
Future<void> _fakeDelay() async {
|
||||
if (!simulatePlatformDelay) {
|
||||
return;
|
||||
}
|
||||
return Future<void>.delayed(const Duration(microseconds: 1));
|
||||
}
|
||||
}
|
||||
|
||||
/// A fake implementation of a native map, which stores all the updates it is
|
||||
/// sent for inspection in tests.
|
||||
class PlatformMapStateRecorder {
|
||||
PlatformMapStateRecorder({
|
||||
required this.widgetConfiguration,
|
||||
this.mapObjects = const MapObjects(),
|
||||
this.mapConfiguration = const MapConfiguration(),
|
||||
}) {
|
||||
markerUpdates.add(MarkerUpdates.from(const <Marker>{}, mapObjects.markers));
|
||||
polygonUpdates
|
||||
.add(PolygonUpdates.from(const <Polygon>{}, mapObjects.polygons));
|
||||
polylineUpdates
|
||||
.add(PolylineUpdates.from(const <Polyline>{}, mapObjects.polylines));
|
||||
circleUpdates.add(CircleUpdates.from(const <Circle>{}, mapObjects.circles));
|
||||
tileOverlaySets.add(mapObjects.tileOverlays);
|
||||
}
|
||||
|
||||
MapWidgetConfiguration widgetConfiguration;
|
||||
MapObjects mapObjects;
|
||||
MapConfiguration mapConfiguration;
|
||||
|
||||
final List<MarkerUpdates> markerUpdates = <MarkerUpdates>[];
|
||||
final List<PolygonUpdates> polygonUpdates = <PolygonUpdates>[];
|
||||
final List<PolylineUpdates> polylineUpdates = <PolylineUpdates>[];
|
||||
final List<CircleUpdates> circleUpdates = <CircleUpdates>[];
|
||||
final List<Set<TileOverlay>> tileOverlaySets = <Set<TileOverlay>>[];
|
||||
}
|
@ -420,41 +420,41 @@ class _ExampleGoogleMapState extends State<ExampleGoogleMap> {
|
||||
return;
|
||||
}
|
||||
final ExampleGoogleMapController controller = await _controller.future;
|
||||
await controller._updateMapConfiguration(updates);
|
||||
unawaited(controller._updateMapConfiguration(updates));
|
||||
_mapConfiguration = newConfig;
|
||||
}
|
||||
|
||||
Future<void> _updateMarkers() async {
|
||||
final ExampleGoogleMapController controller = await _controller.future;
|
||||
await controller._updateMarkers(
|
||||
MarkerUpdates.from(_markers.values.toSet(), widget.markers));
|
||||
unawaited(controller._updateMarkers(
|
||||
MarkerUpdates.from(_markers.values.toSet(), widget.markers)));
|
||||
_markers = keyByMarkerId(widget.markers);
|
||||
}
|
||||
|
||||
Future<void> _updatePolygons() async {
|
||||
final ExampleGoogleMapController controller = await _controller.future;
|
||||
await controller._updatePolygons(
|
||||
PolygonUpdates.from(_polygons.values.toSet(), widget.polygons));
|
||||
unawaited(controller._updatePolygons(
|
||||
PolygonUpdates.from(_polygons.values.toSet(), widget.polygons)));
|
||||
_polygons = keyByPolygonId(widget.polygons);
|
||||
}
|
||||
|
||||
Future<void> _updatePolylines() async {
|
||||
final ExampleGoogleMapController controller = await _controller.future;
|
||||
await controller._updatePolylines(
|
||||
PolylineUpdates.from(_polylines.values.toSet(), widget.polylines));
|
||||
unawaited(controller._updatePolylines(
|
||||
PolylineUpdates.from(_polylines.values.toSet(), widget.polylines)));
|
||||
_polylines = keyByPolylineId(widget.polylines);
|
||||
}
|
||||
|
||||
Future<void> _updateCircles() async {
|
||||
final ExampleGoogleMapController controller = await _controller.future;
|
||||
await controller._updateCircles(
|
||||
CircleUpdates.from(_circles.values.toSet(), widget.circles));
|
||||
unawaited(controller._updateCircles(
|
||||
CircleUpdates.from(_circles.values.toSet(), widget.circles)));
|
||||
_circles = keyByCircleId(widget.circles);
|
||||
}
|
||||
|
||||
Future<void> _updateTileOverlays() async {
|
||||
final ExampleGoogleMapController controller = await _controller.future;
|
||||
await controller._updateTileOverlays(widget.tileOverlays);
|
||||
unawaited(controller._updateTileOverlays(widget.tileOverlays));
|
||||
}
|
||||
|
||||
Future<void> onPlatformViewCreated(int id) async {
|
||||
|
@ -20,5 +20,10 @@ dependencies:
|
||||
path: ../../../
|
||||
google_maps_flutter_platform_interface: ^2.2.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
stream_transform: ^2.0.0
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
@ -0,0 +1,175 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
|
||||
import 'package:maps_example_dart/example_google_map.dart';
|
||||
|
||||
import 'fake_google_maps_flutter_platform.dart';
|
||||
|
||||
Widget _mapWithObjects({
|
||||
Set<Circle> circles = const <Circle>{},
|
||||
Set<Marker> markers = const <Marker>{},
|
||||
Set<Polygon> polygons = const <Polygon>{},
|
||||
Set<Polyline> polylines = const <Polyline>{},
|
||||
Set<TileOverlay> tileOverlays = const <TileOverlay>{},
|
||||
}) {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: ExampleGoogleMap(
|
||||
initialCameraPosition: const CameraPosition(target: LatLng(10.0, 15.0)),
|
||||
circles: circles,
|
||||
markers: markers,
|
||||
polygons: polygons,
|
||||
polylines: polylines,
|
||||
tileOverlays: tileOverlays,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void main() {
|
||||
late FakeGoogleMapsFlutterPlatform platform;
|
||||
|
||||
setUp(() {
|
||||
platform = FakeGoogleMapsFlutterPlatform();
|
||||
GoogleMapsFlutterPlatform.instance = platform;
|
||||
});
|
||||
|
||||
testWidgets('circle updates with delays', (WidgetTester tester) async {
|
||||
platform.simulatePlatformDelay = true;
|
||||
|
||||
const Circle c1 = Circle(circleId: CircleId('circle_1'));
|
||||
const Circle c2 = Circle(circleId: CircleId('circle_2'));
|
||||
const Circle c3 = Circle(circleId: CircleId('circle_3'), radius: 1);
|
||||
const Circle c3updated = Circle(circleId: CircleId('circle_3'), radius: 10);
|
||||
|
||||
// First remove one and add another, then update the new one.
|
||||
await tester.pumpWidget(_mapWithObjects(circles: <Circle>{c1, c2}));
|
||||
await tester.pumpWidget(_mapWithObjects(circles: <Circle>{c1, c3}));
|
||||
await tester.pumpWidget(_mapWithObjects(circles: <Circle>{c1, c3updated}));
|
||||
|
||||
final PlatformMapStateRecorder map = platform.lastCreatedMap;
|
||||
|
||||
expect(map.circleUpdates.length, 3);
|
||||
|
||||
expect(map.circleUpdates[0].circlesToChange.isEmpty, true);
|
||||
expect(map.circleUpdates[0].circlesToAdd, <Circle>{c1, c2});
|
||||
expect(map.circleUpdates[0].circleIdsToRemove.isEmpty, true);
|
||||
|
||||
expect(map.circleUpdates[1].circlesToChange.isEmpty, true);
|
||||
expect(map.circleUpdates[1].circlesToAdd, <Circle>{c3});
|
||||
expect(map.circleUpdates[1].circleIdsToRemove, <CircleId>{c2.circleId});
|
||||
|
||||
expect(map.circleUpdates[2].circlesToChange, <Circle>{c3updated});
|
||||
expect(map.circleUpdates[2].circlesToAdd.isEmpty, true);
|
||||
expect(map.circleUpdates[2].circleIdsToRemove.isEmpty, true);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
});
|
||||
|
||||
testWidgets('marker updates with delays', (WidgetTester tester) async {
|
||||
platform.simulatePlatformDelay = true;
|
||||
|
||||
const Marker m1 = Marker(markerId: MarkerId('marker_1'));
|
||||
const Marker m2 = Marker(markerId: MarkerId('marker_2'));
|
||||
const Marker m3 = Marker(markerId: MarkerId('marker_3'));
|
||||
const Marker m3updated =
|
||||
Marker(markerId: MarkerId('marker_3'), draggable: true);
|
||||
|
||||
// First remove one and add another, then update the new one.
|
||||
await tester.pumpWidget(_mapWithObjects(markers: <Marker>{m1, m2}));
|
||||
await tester.pumpWidget(_mapWithObjects(markers: <Marker>{m1, m3}));
|
||||
await tester.pumpWidget(_mapWithObjects(markers: <Marker>{m1, m3updated}));
|
||||
|
||||
final PlatformMapStateRecorder map = platform.lastCreatedMap;
|
||||
|
||||
expect(map.markerUpdates.length, 3);
|
||||
|
||||
expect(map.markerUpdates[0].markersToChange.isEmpty, true);
|
||||
expect(map.markerUpdates[0].markersToAdd, <Marker>{m1, m2});
|
||||
expect(map.markerUpdates[0].markerIdsToRemove.isEmpty, true);
|
||||
|
||||
expect(map.markerUpdates[1].markersToChange.isEmpty, true);
|
||||
expect(map.markerUpdates[1].markersToAdd, <Marker>{m3});
|
||||
expect(map.markerUpdates[1].markerIdsToRemove, <MarkerId>{m2.markerId});
|
||||
|
||||
expect(map.markerUpdates[2].markersToChange, <Marker>{m3updated});
|
||||
expect(map.markerUpdates[2].markersToAdd.isEmpty, true);
|
||||
expect(map.markerUpdates[2].markerIdsToRemove.isEmpty, true);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
});
|
||||
|
||||
testWidgets('polygon updates with delays', (WidgetTester tester) async {
|
||||
platform.simulatePlatformDelay = true;
|
||||
|
||||
const Polygon p1 = Polygon(polygonId: PolygonId('polygon_1'));
|
||||
const Polygon p2 = Polygon(polygonId: PolygonId('polygon_2'));
|
||||
const Polygon p3 =
|
||||
Polygon(polygonId: PolygonId('polygon_3'), strokeWidth: 1);
|
||||
const Polygon p3updated =
|
||||
Polygon(polygonId: PolygonId('polygon_3'), strokeWidth: 2);
|
||||
|
||||
// First remove one and add another, then update the new one.
|
||||
await tester.pumpWidget(_mapWithObjects(polygons: <Polygon>{p1, p2}));
|
||||
await tester.pumpWidget(_mapWithObjects(polygons: <Polygon>{p1, p3}));
|
||||
await tester
|
||||
.pumpWidget(_mapWithObjects(polygons: <Polygon>{p1, p3updated}));
|
||||
|
||||
final PlatformMapStateRecorder map = platform.lastCreatedMap;
|
||||
|
||||
expect(map.polygonUpdates.length, 3);
|
||||
|
||||
expect(map.polygonUpdates[0].polygonsToChange.isEmpty, true);
|
||||
expect(map.polygonUpdates[0].polygonsToAdd, <Polygon>{p1, p2});
|
||||
expect(map.polygonUpdates[0].polygonIdsToRemove.isEmpty, true);
|
||||
|
||||
expect(map.polygonUpdates[1].polygonsToChange.isEmpty, true);
|
||||
expect(map.polygonUpdates[1].polygonsToAdd, <Polygon>{p3});
|
||||
expect(map.polygonUpdates[1].polygonIdsToRemove, <PolygonId>{p2.polygonId});
|
||||
|
||||
expect(map.polygonUpdates[2].polygonsToChange, <Polygon>{p3updated});
|
||||
expect(map.polygonUpdates[2].polygonsToAdd.isEmpty, true);
|
||||
expect(map.polygonUpdates[2].polygonIdsToRemove.isEmpty, true);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
});
|
||||
|
||||
testWidgets('polyline updates with delays', (WidgetTester tester) async {
|
||||
platform.simulatePlatformDelay = true;
|
||||
|
||||
const Polyline p1 = Polyline(polylineId: PolylineId('polyline_1'));
|
||||
const Polyline p2 = Polyline(polylineId: PolylineId('polyline_2'));
|
||||
const Polyline p3 =
|
||||
Polyline(polylineId: PolylineId('polyline_3'), width: 1);
|
||||
const Polyline p3updated =
|
||||
Polyline(polylineId: PolylineId('polyline_3'), width: 2);
|
||||
|
||||
// First remove one and add another, then update the new one.
|
||||
await tester.pumpWidget(_mapWithObjects(polylines: <Polyline>{p1, p2}));
|
||||
await tester.pumpWidget(_mapWithObjects(polylines: <Polyline>{p1, p3}));
|
||||
await tester
|
||||
.pumpWidget(_mapWithObjects(polylines: <Polyline>{p1, p3updated}));
|
||||
|
||||
final PlatformMapStateRecorder map = platform.lastCreatedMap;
|
||||
|
||||
expect(map.polylineUpdates.length, 3);
|
||||
|
||||
expect(map.polylineUpdates[0].polylinesToChange.isEmpty, true);
|
||||
expect(map.polylineUpdates[0].polylinesToAdd, <Polyline>{p1, p2});
|
||||
expect(map.polylineUpdates[0].polylineIdsToRemove.isEmpty, true);
|
||||
|
||||
expect(map.polylineUpdates[1].polylinesToChange.isEmpty, true);
|
||||
expect(map.polylineUpdates[1].polylinesToAdd, <Polyline>{p3});
|
||||
expect(map.polylineUpdates[1].polylineIdsToRemove,
|
||||
<PolylineId>{p2.polylineId});
|
||||
|
||||
expect(map.polylineUpdates[2].polylinesToChange, <Polyline>{p3updated});
|
||||
expect(map.polylineUpdates[2].polylinesToAdd.isEmpty, true);
|
||||
expect(map.polylineUpdates[2].polylineIdsToRemove.isEmpty, true);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
});
|
||||
}
|
@ -0,0 +1,303 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
|
||||
import 'package:stream_transform/stream_transform.dart';
|
||||
|
||||
// A dummy implementation of the platform interface for tests.
|
||||
class FakeGoogleMapsFlutterPlatform extends GoogleMapsFlutterPlatform {
|
||||
FakeGoogleMapsFlutterPlatform();
|
||||
|
||||
/// The IDs passed to each call to buildView, in call order.
|
||||
List<int> createdIds = <int>[];
|
||||
|
||||
/// A map of creation IDs to fake map instances.
|
||||
Map<int, PlatformMapStateRecorder> mapInstances =
|
||||
<int, PlatformMapStateRecorder>{};
|
||||
|
||||
PlatformMapStateRecorder get lastCreatedMap => mapInstances[createdIds.last]!;
|
||||
|
||||
/// Whether to add a small delay to async calls to simulate more realistic
|
||||
/// async behavior (simulating the platform channel calls most
|
||||
/// implementations will do).
|
||||
///
|
||||
/// When true, requires tests to `pumpAndSettle` at the end of the test
|
||||
/// to avoid exceptions.
|
||||
bool simulatePlatformDelay = false;
|
||||
|
||||
/// Whether `dispose` has been called.
|
||||
bool disposed = false;
|
||||
|
||||
/// Stream controller to inject events for testing.
|
||||
final StreamController<MapEvent<dynamic>> mapEventStreamController =
|
||||
StreamController<MapEvent<dynamic>>.broadcast();
|
||||
|
||||
@override
|
||||
Future<void> init(int mapId) async {}
|
||||
|
||||
@override
|
||||
Future<void> updateMapConfiguration(
|
||||
MapConfiguration update, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
mapInstances[mapId]?.mapConfiguration = update;
|
||||
await _fakeDelay();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateMarkers(
|
||||
MarkerUpdates markerUpdates, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
mapInstances[mapId]?.markerUpdates.add(markerUpdates);
|
||||
await _fakeDelay();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updatePolygons(
|
||||
PolygonUpdates polygonUpdates, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
mapInstances[mapId]?.polygonUpdates.add(polygonUpdates);
|
||||
await _fakeDelay();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updatePolylines(
|
||||
PolylineUpdates polylineUpdates, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
mapInstances[mapId]?.polylineUpdates.add(polylineUpdates);
|
||||
await _fakeDelay();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateCircles(
|
||||
CircleUpdates circleUpdates, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
mapInstances[mapId]?.circleUpdates.add(circleUpdates);
|
||||
await _fakeDelay();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateTileOverlays({
|
||||
required Set<TileOverlay> newTileOverlays,
|
||||
required int mapId,
|
||||
}) async {
|
||||
mapInstances[mapId]?.tileOverlaySets.add(newTileOverlays);
|
||||
await _fakeDelay();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clearTileCache(
|
||||
TileOverlayId tileOverlayId, {
|
||||
required int mapId,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<void> animateCamera(
|
||||
CameraUpdate cameraUpdate, {
|
||||
required int mapId,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<void> moveCamera(
|
||||
CameraUpdate cameraUpdate, {
|
||||
required int mapId,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<void> setMapStyle(
|
||||
String? mapStyle, {
|
||||
required int mapId,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<LatLngBounds> getVisibleRegion({
|
||||
required int mapId,
|
||||
}) async {
|
||||
return LatLngBounds(
|
||||
southwest: const LatLng(0, 0), northeast: const LatLng(0, 0));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ScreenCoordinate> getScreenCoordinate(
|
||||
LatLng latLng, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
return const ScreenCoordinate(x: 0, y: 0);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LatLng> getLatLng(
|
||||
ScreenCoordinate screenCoordinate, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
return const LatLng(0, 0);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> showMarkerInfoWindow(
|
||||
MarkerId markerId, {
|
||||
required int mapId,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<void> hideMarkerInfoWindow(
|
||||
MarkerId markerId, {
|
||||
required int mapId,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<bool> isMarkerInfoWindowShown(
|
||||
MarkerId markerId, {
|
||||
required int mapId,
|
||||
}) async {
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<double> getZoomLevel({
|
||||
required int mapId,
|
||||
}) async {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List?> takeSnapshot({
|
||||
required int mapId,
|
||||
}) async {
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<CameraMoveStartedEvent> onCameraMoveStarted({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<CameraMoveStartedEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<CameraMoveEvent> onCameraMove({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<CameraMoveEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<CameraIdleEvent> onCameraIdle({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<CameraIdleEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<MarkerTapEvent> onMarkerTap({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<MarkerTapEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<InfoWindowTapEvent> onInfoWindowTap({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<InfoWindowTapEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<MarkerDragStartEvent> onMarkerDragStart({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<MarkerDragStartEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<MarkerDragEvent> onMarkerDrag({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<MarkerDragEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<MarkerDragEndEvent> onMarkerDragEnd({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<MarkerDragEndEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<PolylineTapEvent> onPolylineTap({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<PolylineTapEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<PolygonTapEvent> onPolygonTap({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<PolygonTapEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<CircleTapEvent> onCircleTap({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<CircleTapEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<MapTapEvent> onTap({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<MapTapEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<MapLongPressEvent> onLongPress({required int mapId}) {
|
||||
return mapEventStreamController.stream.whereType<MapLongPressEvent>();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose({required int mapId}) {
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildViewWithConfiguration(
|
||||
int creationId,
|
||||
PlatformViewCreatedCallback onPlatformViewCreated, {
|
||||
required MapWidgetConfiguration widgetConfiguration,
|
||||
MapObjects mapObjects = const MapObjects(),
|
||||
MapConfiguration mapConfiguration = const MapConfiguration(),
|
||||
}) {
|
||||
final PlatformMapStateRecorder? instance = mapInstances[creationId];
|
||||
if (instance == null) {
|
||||
createdIds.add(creationId);
|
||||
mapInstances[creationId] = PlatformMapStateRecorder(
|
||||
widgetConfiguration: widgetConfiguration,
|
||||
mapConfiguration: mapConfiguration,
|
||||
mapObjects: mapObjects);
|
||||
onPlatformViewCreated(creationId);
|
||||
}
|
||||
return Container();
|
||||
}
|
||||
|
||||
Future<void> _fakeDelay() async {
|
||||
if (!simulatePlatformDelay) {
|
||||
return;
|
||||
}
|
||||
return Future<void>.delayed(const Duration(microseconds: 1));
|
||||
}
|
||||
}
|
||||
|
||||
/// A fake implementation of a native map, which stores all the updates it is
|
||||
/// sent for inspection in tests.
|
||||
class PlatformMapStateRecorder {
|
||||
PlatformMapStateRecorder({
|
||||
required this.widgetConfiguration,
|
||||
this.mapObjects = const MapObjects(),
|
||||
this.mapConfiguration = const MapConfiguration(),
|
||||
}) {
|
||||
markerUpdates.add(MarkerUpdates.from(const <Marker>{}, mapObjects.markers));
|
||||
polygonUpdates
|
||||
.add(PolygonUpdates.from(const <Polygon>{}, mapObjects.polygons));
|
||||
polylineUpdates
|
||||
.add(PolylineUpdates.from(const <Polyline>{}, mapObjects.polylines));
|
||||
circleUpdates.add(CircleUpdates.from(const <Circle>{}, mapObjects.circles));
|
||||
tileOverlaySets.add(mapObjects.tileOverlays);
|
||||
}
|
||||
|
||||
MapWidgetConfiguration widgetConfiguration;
|
||||
MapObjects mapObjects;
|
||||
MapConfiguration mapConfiguration;
|
||||
|
||||
final List<MarkerUpdates> markerUpdates = <MarkerUpdates>[];
|
||||
final List<PolygonUpdates> polygonUpdates = <PolygonUpdates>[];
|
||||
final List<PolylineUpdates> polylineUpdates = <PolylineUpdates>[];
|
||||
final List<CircleUpdates> circleUpdates = <CircleUpdates>[];
|
||||
final List<Set<TileOverlay>> tileOverlaySets = <Set<TileOverlay>>[];
|
||||
}
|
Reference in New Issue
Block a user