From cb7c704ba6854533a484f9c06a2f6709c2472c80 Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Thu, 6 Aug 2020 19:21:26 -0700 Subject: [PATCH 1/5] [core] Call platform.dispose when on Widget dispose. --- .../google_maps_flutter/google_maps_flutter/CHANGELOG.md | 5 +++++ .../google_maps_flutter/lib/src/controller.dart | 5 +++++ .../google_maps_flutter/lib/src/google_map.dart | 7 +++++++ .../google_maps_flutter/google_maps_flutter/pubspec.yaml | 2 +- 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md index 5d62a5179fd4..f2e77206cff0 100644 --- a/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.5.30 + +* Add a `dispose` method to the controller to let the native side know that we're done with said controller. +* Call `controller.dispose()` from the `dispose` method of the `GoogleMap` widget. + ## 0.5.29 * Pass a constant `_web_only_mapCreationId` to `platform.buildView`, so web can return a cached widget DOM when flutter attempts to repaint there. diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/controller.dart b/packages/google_maps_flutter/google_maps_flutter/lib/src/controller.dart index f5ee180ab1fd..f47b8e57b049 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/controller.dart +++ b/packages/google_maps_flutter/google_maps_flutter/lib/src/controller.dart @@ -258,4 +258,9 @@ class GoogleMapController { Future takeSnapshot() { return _googleMapsFlutterPlatform.takeSnapshot(mapId: mapId); } + + /// Disposes of the platform resources + void dispose() { + _googleMapsFlutterPlatform.dispose(mapId: mapId); + } } diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/google_map.dart b/packages/google_maps_flutter/google_maps_flutter/lib/src/google_map.dart index 5cf3db120ccd..d7f0f1a4e280 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/google_map.dart +++ b/packages/google_maps_flutter/google_maps_flutter/lib/src/google_map.dart @@ -251,6 +251,13 @@ class _GoogleMapState extends State { _circles = keyByCircleId(widget.circles); } + @override + void dispose() async { + super.dispose(); + GoogleMapController controller = await _controller.future; + controller.dispose(); + } + @override void didUpdateWidget(GoogleMap oldWidget) { super.didUpdateWidget(oldWidget); diff --git a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml index 120600a9823c..dd231cf02b46 100644 --- a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml @@ -1,7 +1,7 @@ name: google_maps_flutter description: A Flutter plugin for integrating Google Maps in iOS and Android applications. homepage: https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter -version: 0.5.29 +version: 0.5.30 dependencies: flutter: From 53cd249c856d5c0fe677294c0c16115b97519dfa Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Fri, 7 Aug 2020 16:24:11 -0700 Subject: [PATCH 2/5] Add unit test for Widget disposal... --- .../test/map_creation_test.dart | 82 ++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart b/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart index 7861c86e9709..7ca614f72861 100644 --- a/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart @@ -20,7 +20,8 @@ void main() { setUp(() { // Use a mock platform so we never need to hit the MethodChannel code. GoogleMapsFlutterPlatform.instance = platform; - when(platform.buildView(any, any, any)).thenReturn(Container()); + resetMockitoState(); + _setupMock(platform); }); testWidgets('_webOnlyMapCreationId increments with each GoogleMap widget', ( @@ -61,4 +62,83 @@ void main() { ), ]); }); + + testWidgets('Calls platform.dispose widget is disposed of', ( + WidgetTester tester, + ) async { + await tester.pumpWidget(_DisappearingMap()); + + final _DisappearingMapState state = tester.allStates + .firstWhere((element) => element is _DisappearingMapState); + + // ignore:invalid_use_of_protected_member + state.setState(() { + state.visible = false; + }); + + await tester.pumpAndSettle(); + + verify(platform.dispose(mapId: anyNamed('mapId'))); + }); +} + +// Some test setup classes below... + +class _MockStream extends Mock implements Stream {} + +typedef _CreationCallback = void Function(int); + +// Installs test mocks on the platform +void _setupMock(MockGoogleMapsFlutterPlatform platform) { + // Used to create the view of the map... + when(platform.buildView(any, any, any)).thenAnswer((realInvocation) { + // Call the onPlatformViewCreated callback so the controller gets created. + _CreationCallback onPlatformViewCreatedCb = + realInvocation.positionalArguments[2]; + onPlatformViewCreatedCb.call(0); + return Container(); + }); + // Used to create the Controller + when(platform.onCameraIdle(mapId: anyNamed('mapId'))) + .thenAnswer((_) => _MockStream()); + when(platform.onCameraMove(mapId: anyNamed('mapId'))) + .thenAnswer((_) => _MockStream()); + when(platform.onCameraMoveStarted(mapId: anyNamed('mapId'))) + .thenAnswer((_) => _MockStream()); + when(platform.onCircleTap(mapId: anyNamed('mapId'))) + .thenAnswer((_) => _MockStream()); + when(platform.onInfoWindowTap(mapId: anyNamed('mapId'))) + .thenAnswer((_) => _MockStream()); + when(platform.onLongPress(mapId: anyNamed('mapId'))) + .thenAnswer((_) => _MockStream()); + when(platform.onMarkerDragEnd(mapId: anyNamed('mapId'))) + .thenAnswer((_) => _MockStream()); + when(platform.onMarkerTap(mapId: anyNamed('mapId'))) + .thenAnswer((_) => _MockStream()); + when(platform.onPolygonTap(mapId: anyNamed('mapId'))) + .thenAnswer((_) => _MockStream()); + when(platform.onPolylineTap(mapId: anyNamed('mapId'))) + .thenAnswer((_) => _MockStream()); + when(platform.onTap(mapId: anyNamed('mapId'))) + .thenAnswer((_) => _MockStream()); +} + +/// A class that renders a map when its state.visible = true. +class _DisappearingMap extends StatefulWidget { + @override + State createState() => _DisappearingMapState(); +} + +class _DisappearingMapState extends State<_DisappearingMap> { + bool visible = true; + @override + Widget build(BuildContext context) { + return !visible + ? Container() + : GoogleMap( + initialCameraPosition: CameraPosition( + target: LatLng(43.3608, -5.8702), + ), + ); + } } From 5037e013440b55715dbf9ac45156c25aad71d97d Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Fri, 7 Aug 2020 16:50:15 -0700 Subject: [PATCH 3/5] Retrieve the state more decently. --- .../google_maps_flutter/test/map_creation_test.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart b/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart index 7ca614f72861..9d4a0f3fd738 100644 --- a/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart @@ -68,9 +68,8 @@ void main() { ) async { await tester.pumpWidget(_DisappearingMap()); - final _DisappearingMapState state = tester.allStates - .firstWhere((element) => element is _DisappearingMapState); - + final state = + tester.state<_DisappearingMapState>(find.byType(_DisappearingMap)); // ignore:invalid_use_of_protected_member state.setState(() { state.visible = false; From 81014eb8d7f155a0502fddf1150fde7771d44a63 Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Mon, 10 Aug 2020 10:28:22 -0700 Subject: [PATCH 4/5] Simplify test --- .../test/map_creation_test.dart | 38 ++++--------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart b/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart index 9d4a0f3fd738..5ea9a679a1be 100644 --- a/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart @@ -63,19 +63,17 @@ void main() { ]); }); - testWidgets('Calls platform.dispose widget is disposed of', ( + testWidgets('Calls platform.dispose when GoogleMap is disposed of', ( WidgetTester tester, ) async { - await tester.pumpWidget(_DisappearingMap()); - - final state = - tester.state<_DisappearingMapState>(find.byType(_DisappearingMap)); - // ignore:invalid_use_of_protected_member - state.setState(() { - state.visible = false; - }); + await tester.pumpWidget(GoogleMap( + initialCameraPosition: CameraPosition( + target: LatLng(43.3608, -5.8702), + ), + )); - await tester.pumpAndSettle(); + // Now dispose of the map... + await tester.pumpWidget(Container()); verify(platform.dispose(mapId: anyNamed('mapId'))); }); @@ -121,23 +119,3 @@ void _setupMock(MockGoogleMapsFlutterPlatform platform) { when(platform.onTap(mapId: anyNamed('mapId'))) .thenAnswer((_) => _MockStream()); } - -/// A class that renders a map when its state.visible = true. -class _DisappearingMap extends StatefulWidget { - @override - State createState() => _DisappearingMapState(); -} - -class _DisappearingMapState extends State<_DisappearingMap> { - bool visible = true; - @override - Widget build(BuildContext context) { - return !visible - ? Container() - : GoogleMap( - initialCameraPosition: CameraPosition( - target: LatLng(43.3608, -5.8702), - ), - ); - } -} From 6ae5c2c6c6de0ce01c12e18699b743d1b0fa366e Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Mon, 10 Aug 2020 10:56:58 -0700 Subject: [PATCH 5/5] Update minimum platform interface version. --- packages/google_maps_flutter/google_maps_flutter/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml index dd231cf02b46..e7e3aeeb3327 100644 --- a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml @@ -7,7 +7,7 @@ dependencies: flutter: sdk: flutter flutter_plugin_android_lifecycle: ^1.0.0 - google_maps_flutter_platform_interface: ^1.0.1 + google_maps_flutter_platform_interface: ^1.0.4 dev_dependencies: flutter_test: