Skip to content

Commit f787951

Browse files
[google_maps_flutter_web] Stop listening to map events when disposed (flutter#9250)
Fixes flutter/flutter#168782 ## Pre-Review Checklist - [/] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [/] I read the [Tree Hygiene] page, which explains my responsibilities. - [/] I read and followed the [relevant style guides] and ran [the auto-formatter]. - [/] I signed the [CLA]. - [/] The title of the PR starts with the name of the package surrounded by square brackets, e.g. `[shared_preferences]` - [/] I [linked to at least one issue that this PR fixes] in the description above. - [/] I updated `pubspec.yaml` with an appropriate new version according to the [pub versioning philosophy], or I have commented below to indicate which [version change exemption] this PR falls under[^1]. - [/] I updated `CHANGELOG.md` to add a description of the change, [following repository CHANGELOG style], or I have commented below to indicate which [CHANGELOG exemption] this PR falls under[^1]. - [/] I updated/added any relevant documentation (doc comments with `///`). - [/] I added new tests to check the change I am making, or I have commented below to indicate which [test exemption] this PR falls under[^1]. - [/] All existing and new tests are passing. [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
1 parent af2764c commit f787951

File tree

4 files changed

+90
-17
lines changed

4 files changed

+90
-17
lines changed

packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.5.14+1
2+
3+
* Stops processing events and cancels subscriptions when controller is disposed.
4+
15
## 0.5.14
26

37
* Adds support for disabling or moving the camera control button on web.

packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,46 @@ void main() {
310310
expect(events[4], isA<CameraIdleEvent>());
311311
});
312312

313+
testWidgets('stops listening to map events once disposed', (
314+
WidgetTester tester,
315+
) async {
316+
controller =
317+
createController()
318+
..debugSetOverrides(
319+
createMap: (_, __) => map,
320+
circles: circles,
321+
heatmaps: heatmaps,
322+
markers: markers,
323+
polygons: polygons,
324+
polylines: polylines,
325+
groundOverlays: groundOverlays,
326+
)
327+
..init();
328+
329+
controller.dispose();
330+
331+
// Trigger events on the map, and verify they've been broadcast to the stream
332+
final Stream<MapEvent<Object?>> capturedEvents = stream.stream.take(5);
333+
334+
gmaps.event.trigger(
335+
map,
336+
'click',
337+
gmaps.MapMouseEvent()..latLng = gmaps.LatLng(0, 0),
338+
);
339+
gmaps.event.trigger(
340+
map,
341+
'rightclick',
342+
gmaps.MapMouseEvent()..latLng = gmaps.LatLng(0, 0),
343+
);
344+
// The following line causes 2 events
345+
gmaps.event.trigger(map, 'bounds_changed');
346+
gmaps.event.trigger(map, 'idle');
347+
348+
final List<MapEvent<Object?>> events = await capturedEvents.toList();
349+
350+
expect(events, isEmpty);
351+
});
352+
313353
testWidgets("binds geometry controllers to map's", (
314354
WidgetTester tester,
315355
) async {

packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_controller.dart

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ class GoogleMapController {
139139
TileOverlaysController? _tileOverlaysController;
140140
GroundOverlaysController? _groundOverlaysController;
141141

142+
StreamSubscription<void>? _onClickSubscription;
143+
StreamSubscription<void>? _onRightClickSubscription;
144+
StreamSubscription<void>? _onBoundsChangedSubscription;
145+
StreamSubscription<void>? _onIdleSubscription;
146+
142147
// Keeps track if _attachGeometryControllers has been called or not.
143148
bool _controllersBoundToMap = false;
144149

@@ -247,32 +252,48 @@ class GoogleMapController {
247252
void _attachMapEvents(gmaps.Map map) {
248253
map.onTilesloaded.first.then((void _) {
249254
// Report the map as ready to go the first time the tiles load
250-
_streamController.add(WebMapReadyEvent(_mapId));
255+
if (!_streamController.isClosed) {
256+
_streamController.add(WebMapReadyEvent(_mapId));
257+
}
251258
});
252-
map.onClick.listen((gmaps.MapMouseEventOrIconMouseEvent event) {
259+
_onClickSubscription = map.onClick.listen((
260+
gmaps.MapMouseEventOrIconMouseEvent event,
261+
) {
253262
assert(event.latLng != null);
254-
_streamController.add(
255-
MapTapEvent(_mapId, gmLatLngToLatLng(event.latLng!)),
256-
);
263+
if (!_streamController.isClosed) {
264+
_streamController.add(
265+
MapTapEvent(_mapId, gmLatLngToLatLng(event.latLng!)),
266+
);
267+
}
257268
});
258-
map.onRightclick.listen((gmaps.MapMouseEvent event) {
269+
_onRightClickSubscription = map.onRightclick.listen((
270+
gmaps.MapMouseEvent event,
271+
) {
259272
assert(event.latLng != null);
260-
_streamController.add(
261-
MapLongPressEvent(_mapId, gmLatLngToLatLng(event.latLng!)),
262-
);
273+
if (!_streamController.isClosed) {
274+
_streamController.add(
275+
MapLongPressEvent(_mapId, gmLatLngToLatLng(event.latLng!)),
276+
);
277+
}
263278
});
264-
map.onBoundsChanged.listen((void _) {
279+
_onBoundsChangedSubscription = map.onBoundsChanged.listen((void _) {
265280
if (!_mapIsMoving) {
266281
_mapIsMoving = true;
267-
_streamController.add(CameraMoveStartedEvent(_mapId));
282+
if (!_streamController.isClosed) {
283+
_streamController.add(CameraMoveStartedEvent(_mapId));
284+
}
285+
}
286+
if (!_streamController.isClosed) {
287+
_streamController.add(
288+
CameraMoveEvent(_mapId, _gmViewportToCameraPosition(map)),
289+
);
268290
}
269-
_streamController.add(
270-
CameraMoveEvent(_mapId, _gmViewportToCameraPosition(map)),
271-
);
272291
});
273-
map.onIdle.listen((void _) {
292+
_onIdleSubscription = map.onIdle.listen((void _) {
274293
_mapIsMoving = false;
275-
_streamController.add(CameraIdleEvent(_mapId));
294+
if (!_streamController.isClosed) {
295+
_streamController.add(CameraIdleEvent(_mapId));
296+
}
276297
});
277298
}
278299

@@ -648,6 +669,14 @@ class GoogleMapController {
648669
_clusterManagersController = null;
649670
_tileOverlaysController = null;
650671
_groundOverlaysController = null;
672+
_onClickSubscription?.cancel();
673+
_onClickSubscription = null;
674+
_onRightClickSubscription?.cancel();
675+
_onRightClickSubscription = null;
676+
_onBoundsChangedSubscription?.cancel();
677+
_onBoundsChangedSubscription = null;
678+
_onIdleSubscription?.cancel();
679+
_onIdleSubscription = null;
651680
_streamController.close();
652681
}
653682
}

packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: google_maps_flutter_web
22
description: Web platform implementation of google_maps_flutter
33
repository: https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter_web
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22
5-
version: 0.5.14
5+
version: 0.5.14+1
66

77
environment:
88
sdk: ^3.7.0

0 commit comments

Comments
 (0)