Skip to content

Commit f3f2c7b

Browse files
[google_maps_flutter] Fix async handling in examples (flutter#4729)
Applies the fixes from flutter/packages#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.
1 parent 33dacd6 commit f3f2c7b

File tree

9 files changed

+983
-20
lines changed

9 files changed

+983
-20
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
maps.key=SomeKeyHere

packages/google_maps_flutter/google_maps_flutter_android/example/lib/example_google_map.dart

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -420,41 +420,41 @@ class _ExampleGoogleMapState extends State<ExampleGoogleMap> {
420420
return;
421421
}
422422
final ExampleGoogleMapController controller = await _controller.future;
423-
await controller._updateMapConfiguration(updates);
423+
unawaited(controller._updateMapConfiguration(updates));
424424
_mapConfiguration = newConfig;
425425
}
426426

427427
Future<void> _updateMarkers() async {
428428
final ExampleGoogleMapController controller = await _controller.future;
429-
await controller._updateMarkers(
430-
MarkerUpdates.from(_markers.values.toSet(), widget.markers));
429+
unawaited(controller._updateMarkers(
430+
MarkerUpdates.from(_markers.values.toSet(), widget.markers)));
431431
_markers = keyByMarkerId(widget.markers);
432432
}
433433

434434
Future<void> _updatePolygons() async {
435435
final ExampleGoogleMapController controller = await _controller.future;
436-
await controller._updatePolygons(
437-
PolygonUpdates.from(_polygons.values.toSet(), widget.polygons));
436+
unawaited(controller._updatePolygons(
437+
PolygonUpdates.from(_polygons.values.toSet(), widget.polygons)));
438438
_polygons = keyByPolygonId(widget.polygons);
439439
}
440440

441441
Future<void> _updatePolylines() async {
442442
final ExampleGoogleMapController controller = await _controller.future;
443-
await controller._updatePolylines(
444-
PolylineUpdates.from(_polylines.values.toSet(), widget.polylines));
443+
unawaited(controller._updatePolylines(
444+
PolylineUpdates.from(_polylines.values.toSet(), widget.polylines)));
445445
_polylines = keyByPolylineId(widget.polylines);
446446
}
447447

448448
Future<void> _updateCircles() async {
449449
final ExampleGoogleMapController controller = await _controller.future;
450-
await controller._updateCircles(
451-
CircleUpdates.from(_circles.values.toSet(), widget.circles));
450+
unawaited(controller._updateCircles(
451+
CircleUpdates.from(_circles.values.toSet(), widget.circles)));
452452
_circles = keyByCircleId(widget.circles);
453453
}
454454

455455
Future<void> _updateTileOverlays() async {
456456
final ExampleGoogleMapController controller = await _controller.future;
457-
await controller._updateTileOverlays(widget.tileOverlays);
457+
unawaited(controller._updateTileOverlays(widget.tileOverlays));
458458
}
459459

460460
Future<void> onPlatformViewCreated(int id) async {

packages/google_maps_flutter/google_maps_flutter_android/example/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ dev_dependencies:
2727
sdk: flutter
2828
integration_test:
2929
sdk: flutter
30+
stream_transform: ^2.0.0
3031

3132
flutter:
3233
uses-material-design: true
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter/widgets.dart';
6+
import 'package:flutter_test/flutter_test.dart';
7+
import 'package:google_maps_flutter_example/example_google_map.dart';
8+
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
9+
10+
import 'fake_google_maps_flutter_platform.dart';
11+
12+
Widget _mapWithObjects({
13+
Set<Circle> circles = const <Circle>{},
14+
Set<Marker> markers = const <Marker>{},
15+
Set<Polygon> polygons = const <Polygon>{},
16+
Set<Polyline> polylines = const <Polyline>{},
17+
Set<TileOverlay> tileOverlays = const <TileOverlay>{},
18+
}) {
19+
return Directionality(
20+
textDirection: TextDirection.ltr,
21+
child: ExampleGoogleMap(
22+
initialCameraPosition: const CameraPosition(target: LatLng(10.0, 15.0)),
23+
circles: circles,
24+
markers: markers,
25+
polygons: polygons,
26+
polylines: polylines,
27+
tileOverlays: tileOverlays,
28+
),
29+
);
30+
}
31+
32+
void main() {
33+
late FakeGoogleMapsFlutterPlatform platform;
34+
35+
setUp(() {
36+
platform = FakeGoogleMapsFlutterPlatform();
37+
GoogleMapsFlutterPlatform.instance = platform;
38+
});
39+
40+
testWidgets('circle updates with delays', (WidgetTester tester) async {
41+
platform.simulatePlatformDelay = true;
42+
43+
const Circle c1 = Circle(circleId: CircleId('circle_1'));
44+
const Circle c2 = Circle(circleId: CircleId('circle_2'));
45+
const Circle c3 = Circle(circleId: CircleId('circle_3'), radius: 1);
46+
const Circle c3updated = Circle(circleId: CircleId('circle_3'), radius: 10);
47+
48+
// First remove one and add another, then update the new one.
49+
await tester.pumpWidget(_mapWithObjects(circles: <Circle>{c1, c2}));
50+
await tester.pumpWidget(_mapWithObjects(circles: <Circle>{c1, c3}));
51+
await tester.pumpWidget(_mapWithObjects(circles: <Circle>{c1, c3updated}));
52+
53+
final PlatformMapStateRecorder map = platform.lastCreatedMap;
54+
55+
expect(map.circleUpdates.length, 3);
56+
57+
expect(map.circleUpdates[0].circlesToChange.isEmpty, true);
58+
expect(map.circleUpdates[0].circlesToAdd, <Circle>{c1, c2});
59+
expect(map.circleUpdates[0].circleIdsToRemove.isEmpty, true);
60+
61+
expect(map.circleUpdates[1].circlesToChange.isEmpty, true);
62+
expect(map.circleUpdates[1].circlesToAdd, <Circle>{c3});
63+
expect(map.circleUpdates[1].circleIdsToRemove, <CircleId>{c2.circleId});
64+
65+
expect(map.circleUpdates[2].circlesToChange, <Circle>{c3updated});
66+
expect(map.circleUpdates[2].circlesToAdd.isEmpty, true);
67+
expect(map.circleUpdates[2].circleIdsToRemove.isEmpty, true);
68+
69+
await tester.pumpAndSettle();
70+
});
71+
72+
testWidgets('marker updates with delays', (WidgetTester tester) async {
73+
platform.simulatePlatformDelay = true;
74+
75+
const Marker m1 = Marker(markerId: MarkerId('marker_1'));
76+
const Marker m2 = Marker(markerId: MarkerId('marker_2'));
77+
const Marker m3 = Marker(markerId: MarkerId('marker_3'));
78+
const Marker m3updated =
79+
Marker(markerId: MarkerId('marker_3'), draggable: true);
80+
81+
// First remove one and add another, then update the new one.
82+
await tester.pumpWidget(_mapWithObjects(markers: <Marker>{m1, m2}));
83+
await tester.pumpWidget(_mapWithObjects(markers: <Marker>{m1, m3}));
84+
await tester.pumpWidget(_mapWithObjects(markers: <Marker>{m1, m3updated}));
85+
86+
final PlatformMapStateRecorder map = platform.lastCreatedMap;
87+
88+
expect(map.markerUpdates.length, 3);
89+
90+
expect(map.markerUpdates[0].markersToChange.isEmpty, true);
91+
expect(map.markerUpdates[0].markersToAdd, <Marker>{m1, m2});
92+
expect(map.markerUpdates[0].markerIdsToRemove.isEmpty, true);
93+
94+
expect(map.markerUpdates[1].markersToChange.isEmpty, true);
95+
expect(map.markerUpdates[1].markersToAdd, <Marker>{m3});
96+
expect(map.markerUpdates[1].markerIdsToRemove, <MarkerId>{m2.markerId});
97+
98+
expect(map.markerUpdates[2].markersToChange, <Marker>{m3updated});
99+
expect(map.markerUpdates[2].markersToAdd.isEmpty, true);
100+
expect(map.markerUpdates[2].markerIdsToRemove.isEmpty, true);
101+
102+
await tester.pumpAndSettle();
103+
});
104+
105+
testWidgets('polygon updates with delays', (WidgetTester tester) async {
106+
platform.simulatePlatformDelay = true;
107+
108+
const Polygon p1 = Polygon(polygonId: PolygonId('polygon_1'));
109+
const Polygon p2 = Polygon(polygonId: PolygonId('polygon_2'));
110+
const Polygon p3 =
111+
Polygon(polygonId: PolygonId('polygon_3'), strokeWidth: 1);
112+
const Polygon p3updated =
113+
Polygon(polygonId: PolygonId('polygon_3'), strokeWidth: 2);
114+
115+
// First remove one and add another, then update the new one.
116+
await tester.pumpWidget(_mapWithObjects(polygons: <Polygon>{p1, p2}));
117+
await tester.pumpWidget(_mapWithObjects(polygons: <Polygon>{p1, p3}));
118+
await tester
119+
.pumpWidget(_mapWithObjects(polygons: <Polygon>{p1, p3updated}));
120+
121+
final PlatformMapStateRecorder map = platform.lastCreatedMap;
122+
123+
expect(map.polygonUpdates.length, 3);
124+
125+
expect(map.polygonUpdates[0].polygonsToChange.isEmpty, true);
126+
expect(map.polygonUpdates[0].polygonsToAdd, <Polygon>{p1, p2});
127+
expect(map.polygonUpdates[0].polygonIdsToRemove.isEmpty, true);
128+
129+
expect(map.polygonUpdates[1].polygonsToChange.isEmpty, true);
130+
expect(map.polygonUpdates[1].polygonsToAdd, <Polygon>{p3});
131+
expect(map.polygonUpdates[1].polygonIdsToRemove, <PolygonId>{p2.polygonId});
132+
133+
expect(map.polygonUpdates[2].polygonsToChange, <Polygon>{p3updated});
134+
expect(map.polygonUpdates[2].polygonsToAdd.isEmpty, true);
135+
expect(map.polygonUpdates[2].polygonIdsToRemove.isEmpty, true);
136+
137+
await tester.pumpAndSettle();
138+
});
139+
140+
testWidgets('polyline updates with delays', (WidgetTester tester) async {
141+
platform.simulatePlatformDelay = true;
142+
143+
const Polyline p1 = Polyline(polylineId: PolylineId('polyline_1'));
144+
const Polyline p2 = Polyline(polylineId: PolylineId('polyline_2'));
145+
const Polyline p3 =
146+
Polyline(polylineId: PolylineId('polyline_3'), width: 1);
147+
const Polyline p3updated =
148+
Polyline(polylineId: PolylineId('polyline_3'), width: 2);
149+
150+
// First remove one and add another, then update the new one.
151+
await tester.pumpWidget(_mapWithObjects(polylines: <Polyline>{p1, p2}));
152+
await tester.pumpWidget(_mapWithObjects(polylines: <Polyline>{p1, p3}));
153+
await tester
154+
.pumpWidget(_mapWithObjects(polylines: <Polyline>{p1, p3updated}));
155+
156+
final PlatformMapStateRecorder map = platform.lastCreatedMap;
157+
158+
expect(map.polylineUpdates.length, 3);
159+
160+
expect(map.polylineUpdates[0].polylinesToChange.isEmpty, true);
161+
expect(map.polylineUpdates[0].polylinesToAdd, <Polyline>{p1, p2});
162+
expect(map.polylineUpdates[0].polylineIdsToRemove.isEmpty, true);
163+
164+
expect(map.polylineUpdates[1].polylinesToChange.isEmpty, true);
165+
expect(map.polylineUpdates[1].polylinesToAdd, <Polyline>{p3});
166+
expect(map.polylineUpdates[1].polylineIdsToRemove,
167+
<PolylineId>{p2.polylineId});
168+
169+
expect(map.polylineUpdates[2].polylinesToChange, <Polyline>{p3updated});
170+
expect(map.polylineUpdates[2].polylinesToAdd.isEmpty, true);
171+
expect(map.polylineUpdates[2].polylineIdsToRemove.isEmpty, true);
172+
173+
await tester.pumpAndSettle();
174+
});
175+
}

0 commit comments

Comments
 (0)