[google_maps_flutter] Migrate platform interface to null safety (#3539)
Part of flutter/flutter#75236
Includes a significant refactor of the various overlay objects to remove a lot of identical code across the objects.
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md
index 4273f59..c530c31 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md
@@ -1,3 +1,12 @@
+## 2.0.0-nullsafety
+
+* Migrated to null-safety.
+* BREAKING CHANGE: Removed deprecated APIs.
+* BREAKING CHANGE: Many sets in APIs that used to treat null and empty set as
+ equivalent now require passing an empty set.
+* BREAKING CHANGE: toJson now always returns an `Object`; the details of the
+ object type and structure should be treated as an implementation detail.
+
## 1.2.0
* Add TileOverlay support.
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/method_channel/method_channel_google_maps_flutter.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/method_channel/method_channel_google_maps_flutter.dart
index 8b7af2c..3d16127 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/method_channel/method_channel_google_maps_flutter.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/method_channel/method_channel_google_maps_flutter.dart
@@ -15,6 +15,26 @@
import '../types/tile_overlay_updates.dart';
import '../types/utils/tile_overlay.dart';
+/// Error thrown when an unknown map ID is provided to a method channel API.
+class UnknownMapIDError extends Error {
+ /// Creates an assertion error with the provided [mapId] and optional
+ /// [message].
+ UnknownMapIDError(this.mapId, [this.message]);
+
+ /// The unknown ID.
+ final int mapId;
+
+ /// Message describing the assertion error.
+ final Object? message;
+
+ String toString() {
+ if (message != null) {
+ return "Unknown map ID $mapId: ${Error.safeToString(message)}";
+ }
+ return "Unknown map ID $mapId";
+ }
+}
+
/// An implementation of [GoogleMapsFlutterPlatform] that uses [MethodChannel] to communicate with the native code.
///
/// The `google_maps_flutter` plugin code itself never talks to the native code directly. It delegates
@@ -32,19 +52,20 @@
/// Accesses the MethodChannel associated to the passed mapId.
MethodChannel channel(int mapId) {
- return _channels[mapId];
+ MethodChannel? channel = _channels[mapId];
+ if (channel == null) {
+ throw UnknownMapIDError(mapId);
+ }
+ return channel;
}
// Keep a collection of mapId to a map of TileOverlays.
final Map<int, Map<TileOverlayId, TileOverlay>> _tileOverlays = {};
- /// Initializes the platform interface with [id].
- ///
- /// This method is called when the plugin is first initialized.
@override
Future<void> init(int mapId) {
- MethodChannel channel;
- if (!_channels.containsKey(mapId)) {
+ MethodChannel? channel = _channels[mapId];
+ if (channel == null) {
channel = MethodChannel('plugins.flutter.io/google_maps_$mapId');
channel.setMethodCallHandler(
(MethodCall call) => _handleMethodCall(call, mapId));
@@ -53,9 +74,8 @@
return channel.invokeMethod<void>('map#waitForMap');
}
- /// Dispose of the native resources.
@override
- void dispose({int mapId}) {
+ void dispose({required int mapId}) {
// Noop!
}
@@ -72,57 +92,57 @@
_mapEventStreamController.stream.where((event) => event.mapId == mapId);
@override
- Stream<CameraMoveStartedEvent> onCameraMoveStarted({@required int mapId}) {
+ Stream<CameraMoveStartedEvent> onCameraMoveStarted({required int mapId}) {
return _events(mapId).whereType<CameraMoveStartedEvent>();
}
@override
- Stream<CameraMoveEvent> onCameraMove({@required int mapId}) {
+ Stream<CameraMoveEvent> onCameraMove({required int mapId}) {
return _events(mapId).whereType<CameraMoveEvent>();
}
@override
- Stream<CameraIdleEvent> onCameraIdle({@required int mapId}) {
+ Stream<CameraIdleEvent> onCameraIdle({required int mapId}) {
return _events(mapId).whereType<CameraIdleEvent>();
}
@override
- Stream<MarkerTapEvent> onMarkerTap({@required int mapId}) {
+ Stream<MarkerTapEvent> onMarkerTap({required int mapId}) {
return _events(mapId).whereType<MarkerTapEvent>();
}
@override
- Stream<InfoWindowTapEvent> onInfoWindowTap({@required int mapId}) {
+ Stream<InfoWindowTapEvent> onInfoWindowTap({required int mapId}) {
return _events(mapId).whereType<InfoWindowTapEvent>();
}
@override
- Stream<MarkerDragEndEvent> onMarkerDragEnd({@required int mapId}) {
+ Stream<MarkerDragEndEvent> onMarkerDragEnd({required int mapId}) {
return _events(mapId).whereType<MarkerDragEndEvent>();
}
@override
- Stream<PolylineTapEvent> onPolylineTap({@required int mapId}) {
+ Stream<PolylineTapEvent> onPolylineTap({required int mapId}) {
return _events(mapId).whereType<PolylineTapEvent>();
}
@override
- Stream<PolygonTapEvent> onPolygonTap({@required int mapId}) {
+ Stream<PolygonTapEvent> onPolygonTap({required int mapId}) {
return _events(mapId).whereType<PolygonTapEvent>();
}
@override
- Stream<CircleTapEvent> onCircleTap({@required int mapId}) {
+ Stream<CircleTapEvent> onCircleTap({required int mapId}) {
return _events(mapId).whereType<CircleTapEvent>();
}
@override
- Stream<MapTapEvent> onTap({@required int mapId}) {
+ Stream<MapTapEvent> onTap({required int mapId}) {
return _events(mapId).whereType<MapTapEvent>();
}
@override
- Stream<MapLongPressEvent> onLongPress({@required int mapId}) {
+ Stream<MapLongPressEvent> onLongPress({required int mapId}) {
return _events(mapId).whereType<MapLongPressEvent>();
}
@@ -134,7 +154,7 @@
case 'camera#onMove':
_mapEventStreamController.add(CameraMoveEvent(
mapId,
- CameraPosition.fromMap(call.arguments['position']),
+ CameraPosition.fromMap(call.arguments['position'])!,
));
break;
case 'camera#onIdle':
@@ -149,7 +169,7 @@
case 'marker#onDragEnd':
_mapEventStreamController.add(MarkerDragEndEvent(
mapId,
- LatLng.fromJson(call.arguments['position']),
+ LatLng.fromJson(call.arguments['position'])!,
MarkerId(call.arguments['markerId']),
));
break;
@@ -180,26 +200,26 @@
case 'map#onTap':
_mapEventStreamController.add(MapTapEvent(
mapId,
- LatLng.fromJson(call.arguments['position']),
+ LatLng.fromJson(call.arguments['position'])!,
));
break;
case 'map#onLongPress':
_mapEventStreamController.add(MapLongPressEvent(
mapId,
- LatLng.fromJson(call.arguments['position']),
+ LatLng.fromJson(call.arguments['position'])!,
));
break;
case 'tileOverlay#getTile':
- final Map<TileOverlayId, TileOverlay> tileOverlaysForThisMap =
+ final Map<TileOverlayId, TileOverlay>? tileOverlaysForThisMap =
_tileOverlays[mapId];
final String tileOverlayId = call.arguments['tileOverlayId'];
- final TileOverlay tileOverlay =
- tileOverlaysForThisMap[TileOverlayId(tileOverlayId)];
- Tile tile;
- if (tileOverlay == null || tileOverlay.tileProvider == null) {
+ final TileOverlay? tileOverlay =
+ tileOverlaysForThisMap?[TileOverlayId(tileOverlayId)];
+ TileProvider? tileProvider = tileOverlay?.tileProvider;
+ if (tileProvider == null) {
return TileProvider.noTile.toJson();
}
- tile = await tileOverlay.tileProvider.getTile(
+ final Tile tile = await tileProvider.getTile(
call.arguments['x'],
call.arguments['y'],
call.arguments['zoom'],
@@ -210,16 +230,10 @@
}
}
- /// Updates configuration options of the map user interface.
- ///
- /// Change listeners are notified once the update has been made on the
- /// platform side.
- ///
- /// The returned [Future] completes after listeners have been notified.
@override
Future<void> updateMapOptions(
Map<String, dynamic> optionsUpdate, {
- @required int mapId,
+ required int mapId,
}) {
assert(optionsUpdate != null);
return channel(mapId).invokeMethod<void>(
@@ -230,16 +244,10 @@
);
}
- /// Updates marker configuration.
- ///
- /// Change listeners are notified once the update has been made on the
- /// platform side.
- ///
- /// The returned [Future] completes after listeners have been notified.
@override
Future<void> updateMarkers(
MarkerUpdates markerUpdates, {
- @required int mapId,
+ required int mapId,
}) {
assert(markerUpdates != null);
return channel(mapId).invokeMethod<void>(
@@ -248,16 +256,10 @@
);
}
- /// Updates polygon configuration.
- ///
- /// Change listeners are notified once the update has been made on the
- /// platform side.
- ///
- /// The returned [Future] completes after listeners have been notified.
@override
Future<void> updatePolygons(
PolygonUpdates polygonUpdates, {
- @required int mapId,
+ required int mapId,
}) {
assert(polygonUpdates != null);
return channel(mapId).invokeMethod<void>(
@@ -266,16 +268,10 @@
);
}
- /// Updates polyline configuration.
- ///
- /// Change listeners are notified once the update has been made on the
- /// platform side.
- ///
- /// The returned [Future] completes after listeners have been notified.
@override
Future<void> updatePolylines(
PolylineUpdates polylineUpdates, {
- @required int mapId,
+ required int mapId,
}) {
assert(polylineUpdates != null);
return channel(mapId).invokeMethod<void>(
@@ -284,16 +280,10 @@
);
}
- /// Updates circle configuration.
- ///
- /// Change listeners are notified once the update has been made on the
- /// platform side.
- ///
- /// The returned [Future] completes after listeners have been notified.
@override
Future<void> updateCircles(
CircleUpdates circleUpdates, {
- @required int mapId,
+ required int mapId,
}) {
assert(circleUpdates != null);
return channel(mapId).invokeMethod<void>(
@@ -302,23 +292,16 @@
);
}
- /// Updates tile overlay configuration.
- ///
- /// Change listeners are notified once the update has been made on the
- /// platform side.
- ///
- /// The returned [Future] completes after listeners have been notified.
- ///
- /// If `newTileOverlays` is null, all the [TileOverlays] are removed for the Map with `mapId`.
@override
Future<void> updateTileOverlays({
- Set<TileOverlay> newTileOverlays,
- @required int mapId,
+ required Set<TileOverlay> newTileOverlays,
+ required int mapId,
}) {
- final Map<TileOverlayId, TileOverlay> currentTileOverlays =
+ final Map<TileOverlayId, TileOverlay>? currentTileOverlays =
_tileOverlays[mapId];
- Set<TileOverlay> previousSet =
- currentTileOverlays != null ? currentTileOverlays.values.toSet() : null;
+ Set<TileOverlay> previousSet = currentTileOverlays != null
+ ? currentTileOverlays.values.toSet()
+ : <TileOverlay>{};
final TileOverlayUpdates updates =
TileOverlayUpdates.from(previousSet, newTileOverlays);
_tileOverlays[mapId] = keyTileOverlayId(newTileOverlays);
@@ -328,203 +311,152 @@
);
}
- /// Clears the tile cache so that all tiles will be requested again from the
- /// [TileProvider].
- ///
- /// The current tiles from this tile overlay will also be
- /// cleared from the map after calling this method. The Google Map SDK maintains a small
- /// in-memory cache of tiles. If you want to cache tiles for longer, you
- /// should implement an on-disk cache.
@override
Future<void> clearTileCache(
TileOverlayId tileOverlayId, {
- @required int mapId,
+ required int mapId,
}) {
return channel(mapId)
- .invokeMethod<void>('tileOverlays#clearTileCache', <String, dynamic>{
+ .invokeMethod<void>('tileOverlays#clearTileCache', <String, Object>{
'tileOverlayId': tileOverlayId.value,
});
}
- /// Starts an animated change of the map camera position.
- ///
- /// The returned [Future] completes after the change has been started on the
- /// platform side.
@override
Future<void> animateCamera(
CameraUpdate cameraUpdate, {
- @required int mapId,
+ required int mapId,
}) {
- return channel(mapId)
- .invokeMethod<void>('camera#animate', <String, dynamic>{
+ return channel(mapId).invokeMethod<void>('camera#animate', <String, Object>{
'cameraUpdate': cameraUpdate.toJson(),
});
}
- /// Changes the map camera position.
- ///
- /// The returned [Future] completes after the change has been made on the
- /// platform side.
@override
Future<void> moveCamera(
CameraUpdate cameraUpdate, {
- @required int mapId,
+ required int mapId,
}) {
return channel(mapId).invokeMethod<void>('camera#move', <String, dynamic>{
'cameraUpdate': cameraUpdate.toJson(),
});
}
- /// Sets the styling of the base map.
- ///
- /// Set to `null` to clear any previous custom styling.
- ///
- /// If problems were detected with the [mapStyle], including un-parsable
- /// styling JSON, unrecognized feature type, unrecognized element type, or
- /// invalid styler keys: [MapStyleException] is thrown and the current
- /// style is left unchanged.
- ///
- /// The style string can be generated using [map style tool](https://mapstyle.withgoogle.com/).
- /// Also, refer [iOS](https://developers.google.com/maps/documentation/ios-sdk/style-reference)
- /// and [Android](https://developers.google.com/maps/documentation/android-sdk/style-reference)
- /// style reference for more information regarding the supported styles.
@override
Future<void> setMapStyle(
- String mapStyle, {
- @required int mapId,
+ String? mapStyle, {
+ required int mapId,
}) async {
- final List<dynamic> successAndError = await channel(mapId)
- .invokeMethod<List<dynamic>>('map#setStyle', mapStyle);
+ final List<dynamic> successAndError = (await channel(mapId)
+ .invokeMethod<List<dynamic>>('map#setStyle', mapStyle))!;
final bool success = successAndError[0];
if (!success) {
throw MapStyleException(successAndError[1]);
}
}
- /// Return the region that is visible in a map.
@override
Future<LatLngBounds> getVisibleRegion({
- @required int mapId,
+ required int mapId,
}) async {
- final Map<String, dynamic> latLngBounds = await channel(mapId)
- .invokeMapMethod<String, dynamic>('map#getVisibleRegion');
- final LatLng southwest = LatLng.fromJson(latLngBounds['southwest']);
- final LatLng northeast = LatLng.fromJson(latLngBounds['northeast']);
+ final Map<String, dynamic> latLngBounds = (await channel(mapId)
+ .invokeMapMethod<String, dynamic>('map#getVisibleRegion'))!;
+ final LatLng southwest = LatLng.fromJson(latLngBounds['southwest'])!;
+ final LatLng northeast = LatLng.fromJson(latLngBounds['northeast'])!;
return LatLngBounds(northeast: northeast, southwest: southwest);
}
- /// Return point [Map<String, int>] of the [screenCoordinateInJson] in the current map view.
- ///
- /// A projection is used to translate between on screen location and geographic coordinates.
- /// Screen location is in screen pixels (not display pixels) with respect to the top left corner
- /// of the map, not necessarily of the whole screen.
@override
Future<ScreenCoordinate> getScreenCoordinate(
LatLng latLng, {
- @required int mapId,
+ required int mapId,
}) async {
- final Map<String, int> point = await channel(mapId)
+ final Map<String, int> point = (await channel(mapId)
.invokeMapMethod<String, int>(
- 'map#getScreenCoordinate', latLng.toJson());
+ 'map#getScreenCoordinate', latLng.toJson()))!;
- return ScreenCoordinate(x: point['x'], y: point['y']);
+ return ScreenCoordinate(x: point['x']!, y: point['y']!);
}
- /// Returns [LatLng] corresponding to the [ScreenCoordinate] in the current map view.
- ///
- /// Returned [LatLng] corresponds to a screen location. The screen location is specified in screen
- /// pixels (not display pixels) relative to the top left of the map, not top left of the whole screen.
@override
Future<LatLng> getLatLng(
ScreenCoordinate screenCoordinate, {
- @required int mapId,
+ required int mapId,
}) async {
- final List<dynamic> latLng = await channel(mapId)
+ final List<dynamic> latLng = (await channel(mapId)
.invokeMethod<List<dynamic>>(
- 'map#getLatLng', screenCoordinate.toJson());
+ 'map#getLatLng', screenCoordinate.toJson()))!;
return LatLng(latLng[0], latLng[1]);
}
- /// Programmatically show the Info Window for a [Marker].
- ///
- /// The `markerId` must match one of the markers on the map.
- /// An invalid `markerId` triggers an "Invalid markerId" error.
- ///
- /// * See also:
- /// * [hideMarkerInfoWindow] to hide the Info Window.
- /// * [isMarkerInfoWindowShown] to check if the Info Window is showing.
@override
Future<void> showMarkerInfoWindow(
MarkerId markerId, {
- @required int mapId,
+ required int mapId,
}) {
assert(markerId != null);
return channel(mapId).invokeMethod<void>(
'markers#showInfoWindow', <String, String>{'markerId': markerId.value});
}
- /// Programmatically hide the Info Window for a [Marker].
- ///
- /// The `markerId` must match one of the markers on the map.
- /// An invalid `markerId` triggers an "Invalid markerId" error.
- ///
- /// * See also:
- /// * [showMarkerInfoWindow] to show the Info Window.
- /// * [isMarkerInfoWindowShown] to check if the Info Window is showing.
@override
Future<void> hideMarkerInfoWindow(
MarkerId markerId, {
- @required int mapId,
+ required int mapId,
}) {
assert(markerId != null);
return channel(mapId).invokeMethod<void>(
'markers#hideInfoWindow', <String, String>{'markerId': markerId.value});
}
- /// Returns `true` when the [InfoWindow] is showing, `false` otherwise.
- ///
- /// The `markerId` must match one of the markers on the map.
- /// An invalid `markerId` triggers an "Invalid markerId" error.
- ///
- /// * See also:
- /// * [showMarkerInfoWindow] to show the Info Window.
- /// * [hideMarkerInfoWindow] to hide the Info Window.
@override
Future<bool> isMarkerInfoWindowShown(
MarkerId markerId, {
- @required int mapId,
+ required int mapId,
}) {
assert(markerId != null);
return channel(mapId).invokeMethod<bool>('markers#isInfoWindowShown',
- <String, String>{'markerId': markerId.value});
+ <String, String>{'markerId': markerId.value}) as Future<bool>;
}
- /// Returns the current zoom level of the map
@override
Future<double> getZoomLevel({
- @required int mapId,
+ required int mapId,
}) {
- return channel(mapId).invokeMethod<double>('map#getZoomLevel');
+ return channel(mapId).invokeMethod<double>('map#getZoomLevel')
+ as Future<double>;
}
- /// Returns the image bytes of the map
@override
- Future<Uint8List> takeSnapshot({
- @required int mapId,
+ Future<Uint8List?> takeSnapshot({
+ required int mapId,
}) {
return channel(mapId).invokeMethod<Uint8List>('map#takeSnapshot');
}
- /// This method builds the appropriate platform view where the map
- /// can be rendered.
- /// The `mapId` is passed as a parameter from the framework on the
- /// `onPlatformViewCreated` callback.
@override
Widget buildView(
- Map<String, dynamic> creationParams,
- Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
- PlatformViewCreatedCallback onPlatformViewCreated) {
+ int creationId,
+ PlatformViewCreatedCallback onPlatformViewCreated, {
+ required CameraPosition initialCameraPosition,
+ Set<Marker> markers = const <Marker>{},
+ Set<Polygon> polygons = const <Polygon>{},
+ Set<Polyline> polylines = const <Polyline>{},
+ Set<Circle> circles = const <Circle>{},
+ Set<TileOverlay> tileOverlays = const <TileOverlay>{},
+ Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers,
+ Map<String, dynamic> mapOptions = const <String, dynamic>{},
+ }) {
+ final Map<String, dynamic> creationParams = <String, dynamic>{
+ 'initialCameraPosition': initialCameraPosition.toMap(),
+ 'options': mapOptions,
+ 'markersToAdd': serializeMarkerSet(markers),
+ 'polygonsToAdd': serializePolygonSet(polygons),
+ 'polylinesToAdd': serializePolylineSet(polylines),
+ 'circlesToAdd': serializeCircleSet(circles),
+ 'tileOverlaysToAdd': serializeTileOverlaySet(tileOverlays),
+ };
if (defaultTargetPlatform == TargetPlatform.android) {
return AndroidView(
viewType: 'plugins.flutter.io/google_maps',
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_flutter_platform.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_flutter_platform.dart
index b9d3fec..a363fc3 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_flutter_platform.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_flutter_platform.dart
@@ -58,7 +58,7 @@
/// The returned [Future] completes after listeners have been notified.
Future<void> updateMapOptions(
Map<String, dynamic> optionsUpdate, {
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError('updateMapOptions() has not been implemented.');
}
@@ -71,7 +71,7 @@
/// The returned [Future] completes after listeners have been notified.
Future<void> updateMarkers(
MarkerUpdates markerUpdates, {
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError('updateMarkers() has not been implemented.');
}
@@ -84,7 +84,7 @@
/// The returned [Future] completes after listeners have been notified.
Future<void> updatePolygons(
PolygonUpdates polygonUpdates, {
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError('updatePolygons() has not been implemented.');
}
@@ -97,7 +97,7 @@
/// The returned [Future] completes after listeners have been notified.
Future<void> updatePolylines(
PolylineUpdates polylineUpdates, {
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError('updatePolylines() has not been implemented.');
}
@@ -110,7 +110,7 @@
/// The returned [Future] completes after listeners have been notified.
Future<void> updateCircles(
CircleUpdates circleUpdates, {
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError('updateCircles() has not been implemented.');
}
@@ -122,8 +122,8 @@
///
/// The returned [Future] completes after listeners have been notified.
Future<void> updateTileOverlays({
- Set<TileOverlay> newTileOverlays,
- @required int mapId,
+ required Set<TileOverlay> newTileOverlays,
+ required int mapId,
}) {
throw UnimplementedError('updateTileOverlays() has not been implemented.');
}
@@ -137,7 +137,7 @@
/// should implement an on-disk cache.
Future<void> clearTileCache(
TileOverlayId tileOverlayId, {
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError('clearTileCache() has not been implemented.');
}
@@ -148,7 +148,7 @@
/// platform side.
Future<void> animateCamera(
CameraUpdate cameraUpdate, {
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError('animateCamera() has not been implemented.');
}
@@ -159,7 +159,7 @@
/// platform side.
Future<void> moveCamera(
CameraUpdate cameraUpdate, {
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError('moveCamera() has not been implemented.');
}
@@ -175,15 +175,15 @@
///
/// The style string can be generated using [map style tool](https://mapstyle.withgoogle.com/).
Future<void> setMapStyle(
- String mapStyle, {
- @required int mapId,
+ String? mapStyle, {
+ required int mapId,
}) {
throw UnimplementedError('setMapStyle() has not been implemented.');
}
/// Return the region that is visible in a map.
Future<LatLngBounds> getVisibleRegion({
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError('getVisibleRegion() has not been implemented.');
}
@@ -195,7 +195,7 @@
/// of the map, not necessarily of the whole screen.
Future<ScreenCoordinate> getScreenCoordinate(
LatLng latLng, {
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError('getScreenCoordinate() has not been implemented.');
}
@@ -207,7 +207,7 @@
/// of the map, not necessarily of the whole screen.
Future<LatLng> getLatLng(
ScreenCoordinate screenCoordinate, {
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError('getLatLng() has not been implemented.');
}
@@ -222,7 +222,7 @@
/// * [isMarkerInfoWindowShown] to check if the Info Window is showing.
Future<void> showMarkerInfoWindow(
MarkerId markerId, {
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError(
'showMarkerInfoWindow() has not been implemented.');
@@ -238,7 +238,7 @@
/// * [isMarkerInfoWindowShown] to check if the Info Window is showing.
Future<void> hideMarkerInfoWindow(
MarkerId markerId, {
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError(
'hideMarkerInfoWindow() has not been implemented.');
@@ -254,21 +254,23 @@
/// * [hideMarkerInfoWindow] to hide the Info Window.
Future<bool> isMarkerInfoWindowShown(
MarkerId markerId, {
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError('updateMapOptions() has not been implemented.');
}
- /// Returns the current zoom level of the map
+ /// Returns the current zoom level of the map.
Future<double> getZoomLevel({
- @required int mapId,
+ required int mapId,
}) {
throw UnimplementedError('getZoomLevel() has not been implemented.');
}
- /// Returns the image bytes of the map
- Future<Uint8List> takeSnapshot({
- @required int mapId,
+ /// Returns the image bytes of the map.
+ ///
+ /// Returns null if a snapshot cannot be created.
+ Future<Uint8List?> takeSnapshot({
+ required int mapId,
}) {
throw UnimplementedError('takeSnapshot() has not been implemented.');
}
@@ -277,70 +279,81 @@
// into the plugin
/// The Camera started moving.
- Stream<CameraMoveStartedEvent> onCameraMoveStarted({@required int mapId}) {
+ Stream<CameraMoveStartedEvent> onCameraMoveStarted({required int mapId}) {
throw UnimplementedError('onCameraMoveStarted() has not been implemented.');
}
/// The Camera finished moving to a new [CameraPosition].
- Stream<CameraMoveEvent> onCameraMove({@required int mapId}) {
+ Stream<CameraMoveEvent> onCameraMove({required int mapId}) {
throw UnimplementedError('onCameraMove() has not been implemented.');
}
/// The Camera is now idle.
- Stream<CameraIdleEvent> onCameraIdle({@required int mapId}) {
+ Stream<CameraIdleEvent> onCameraIdle({required int mapId}) {
throw UnimplementedError('onCameraMove() has not been implemented.');
}
/// A [Marker] has been tapped.
- Stream<MarkerTapEvent> onMarkerTap({@required int mapId}) {
+ Stream<MarkerTapEvent> onMarkerTap({required int mapId}) {
throw UnimplementedError('onMarkerTap() has not been implemented.');
}
/// An [InfoWindow] has been tapped.
- Stream<InfoWindowTapEvent> onInfoWindowTap({@required int mapId}) {
+ Stream<InfoWindowTapEvent> onInfoWindowTap({required int mapId}) {
throw UnimplementedError('onInfoWindowTap() has not been implemented.');
}
/// A [Marker] has been dragged to a different [LatLng] position.
- Stream<MarkerDragEndEvent> onMarkerDragEnd({@required int mapId}) {
+ Stream<MarkerDragEndEvent> onMarkerDragEnd({required int mapId}) {
throw UnimplementedError('onMarkerDragEnd() has not been implemented.');
}
/// A [Polyline] has been tapped.
- Stream<PolylineTapEvent> onPolylineTap({@required int mapId}) {
+ Stream<PolylineTapEvent> onPolylineTap({required int mapId}) {
throw UnimplementedError('onPolylineTap() has not been implemented.');
}
/// A [Polygon] has been tapped.
- Stream<PolygonTapEvent> onPolygonTap({@required int mapId}) {
+ Stream<PolygonTapEvent> onPolygonTap({required int mapId}) {
throw UnimplementedError('onPolygonTap() has not been implemented.');
}
/// A [Circle] has been tapped.
- Stream<CircleTapEvent> onCircleTap({@required int mapId}) {
+ Stream<CircleTapEvent> onCircleTap({required int mapId}) {
throw UnimplementedError('onCircleTap() has not been implemented.');
}
/// A Map has been tapped at a certain [LatLng].
- Stream<MapTapEvent> onTap({@required int mapId}) {
+ Stream<MapTapEvent> onTap({required int mapId}) {
throw UnimplementedError('onTap() has not been implemented.');
}
/// A Map has been long-pressed at a certain [LatLng].
- Stream<MapLongPressEvent> onLongPress({@required int mapId}) {
+ Stream<MapLongPressEvent> onLongPress({required int mapId}) {
throw UnimplementedError('onLongPress() has not been implemented.');
}
/// Dispose of whatever resources the `mapId` is holding on to.
- void dispose({@required int mapId}) {
+ void dispose({required int mapId}) {
throw UnimplementedError('dispose() has not been implemented.');
}
/// Returns a widget displaying the map view
Widget buildView(
- Map<String, dynamic> creationParams,
- Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
- PlatformViewCreatedCallback onPlatformViewCreated) {
+ int creationId,
+ PlatformViewCreatedCallback onPlatformViewCreated, {
+ required CameraPosition initialCameraPosition,
+ Set<Marker> markers = const <Marker>{},
+ Set<Polygon> polygons = const <Polygon>{},
+ Set<Polyline> polylines = const <Polyline>{},
+ Set<Circle> circles = const <Circle>{},
+ Set<TileOverlay> tileOverlays = const <TileOverlay>{},
+ Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers =
+ const <Factory<OneSequenceGestureRecognizer>>{},
+ // TODO: Replace with a structured type that's part of the interface.
+ // See https://github.com/flutter/flutter/issues/70330.
+ Map<String, dynamic> mapOptions = const <String, dynamic>{},
+ }) {
throw UnimplementedError('buildView() has not been implemented.');
}
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart
index e10481e..cc98875 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart
@@ -4,6 +4,7 @@
import 'dart:async' show Future;
import 'dart:typed_data' show Uint8List;
+import 'dart:ui' show Size;
import 'package:flutter/material.dart'
show ImageConfiguration, AssetImage, AssetBundleImageKey;
@@ -61,28 +62,14 @@
/// Creates a BitmapDescriptor that refers to the default marker image.
static const BitmapDescriptor defaultMarker =
- BitmapDescriptor._(<dynamic>[_defaultMarker]);
+ BitmapDescriptor._(<Object>[_defaultMarker]);
/// Creates a BitmapDescriptor that refers to a colorization of the default
/// marker image. For convenience, there is a predefined set of hue values.
/// See e.g. [hueYellow].
static BitmapDescriptor defaultMarkerWithHue(double hue) {
assert(0.0 <= hue && hue < 360.0);
- return BitmapDescriptor._(<dynamic>[_defaultMarker, hue]);
- }
-
- /// Creates a BitmapDescriptor using the name of a bitmap image in the assets
- /// directory.
- ///
- /// Use [fromAssetImage]. This method does not respect the screen dpi when
- /// picking an asset image.
- @Deprecated("Use fromAssetImage instead")
- static BitmapDescriptor fromAsset(String assetName, {String package}) {
- if (package == null) {
- return BitmapDescriptor._(<dynamic>[_fromAsset, assetName]);
- } else {
- return BitmapDescriptor._(<dynamic>[_fromAsset, assetName, package]);
- }
+ return BitmapDescriptor._(<Object>[_defaultMarker, hue]);
}
/// Creates a [BitmapDescriptor] from an asset image.
@@ -95,29 +82,31 @@
static Future<BitmapDescriptor> fromAssetImage(
ImageConfiguration configuration,
String assetName, {
- AssetBundle bundle,
- String package,
+ AssetBundle? bundle,
+ String? package,
bool mipmaps = true,
}) async {
- if (!mipmaps && configuration.devicePixelRatio != null) {
- return BitmapDescriptor._(<dynamic>[
+ double? devicePixelRatio = configuration.devicePixelRatio;
+ if (!mipmaps && devicePixelRatio != null) {
+ return BitmapDescriptor._(<Object>[
_fromAssetImage,
assetName,
- configuration.devicePixelRatio,
+ devicePixelRatio,
]);
}
final AssetImage assetImage =
AssetImage(assetName, package: package, bundle: bundle);
final AssetBundleImageKey assetBundleImageKey =
await assetImage.obtainKey(configuration);
- return BitmapDescriptor._(<dynamic>[
+ final Size? size = configuration.size;
+ return BitmapDescriptor._(<Object>[
_fromAssetImage,
assetBundleImageKey.name,
assetBundleImageKey.scale,
- if (kIsWeb && configuration?.size != null)
+ if (kIsWeb && size != null)
[
- configuration.size.width,
- configuration.size.height,
+ size.width,
+ size.height,
],
]);
}
@@ -125,45 +114,47 @@
/// Creates a BitmapDescriptor using an array of bytes that must be encoded
/// as PNG.
static BitmapDescriptor fromBytes(Uint8List byteData) {
- return BitmapDescriptor._(<dynamic>[_fromBytes, byteData]);
+ return BitmapDescriptor._(<Object>[_fromBytes, byteData]);
}
/// The inverse of .toJson.
// This is needed in Web to re-hydrate BitmapDescriptors that have been
// transformed to JSON for transport.
// TODO(https://github.com/flutter/flutter/issues/70330): Clean this up.
- BitmapDescriptor.fromJson(dynamic json) : _json = json {
- assert(_validTypes.contains(_json[0]));
- switch (_json[0]) {
+ BitmapDescriptor.fromJson(Object json) : _json = json {
+ assert(_json is List<dynamic>);
+ final jsonList = json as List<dynamic>;
+ assert(_validTypes.contains(jsonList[0]));
+ switch (jsonList[0]) {
case _defaultMarker:
- assert(_json.length <= 2);
- if (_json.length == 2) {
- assert(_json[1] is num);
- assert(0 <= _json[1] && _json[1] < 360);
+ assert(jsonList.length <= 2);
+ if (jsonList.length == 2) {
+ assert(jsonList[1] is num);
+ assert(0 <= jsonList[1] && jsonList[1] < 360);
}
break;
case _fromBytes:
- assert(_json.length == 2);
- assert(_json[1] != null && _json[1] is List<int>);
- assert((_json[1] as List).isNotEmpty);
+ assert(jsonList.length == 2);
+ assert(jsonList[1] != null && jsonList[1] is List<int>);
+ assert((jsonList[1] as List).isNotEmpty);
break;
case _fromAsset:
- assert(_json.length <= 3);
- assert(_json[1] != null && _json[1] is String);
- assert((_json[1] as String).isNotEmpty);
- if (_json.length == 3) {
- assert(_json[2] != null && _json[2] is String);
- assert((_json[2] as String).isNotEmpty);
+ assert(jsonList.length <= 3);
+ assert(jsonList[1] != null && jsonList[1] is String);
+ assert((jsonList[1] as String).isNotEmpty);
+ if (jsonList.length == 3) {
+ assert(jsonList[2] != null && jsonList[2] is String);
+ assert((jsonList[2] as String).isNotEmpty);
}
break;
case _fromAssetImage:
- assert(_json.length <= 4);
- assert(_json[1] != null && _json[1] is String);
- assert((_json[1] as String).isNotEmpty);
- assert(_json[2] != null && _json[2] is double);
- if (_json.length == 4) {
- assert(_json[3] != null && _json[3] is List);
- assert((_json[3] as List).length == 2);
+ assert(jsonList.length <= 4);
+ assert(jsonList[1] != null && jsonList[1] is String);
+ assert((jsonList[1] as String).isNotEmpty);
+ assert(jsonList[2] != null && jsonList[2] is double);
+ if (jsonList.length == 4) {
+ assert(jsonList[3] != null && jsonList[3] is List);
+ assert((jsonList[3] as List).length == 2);
}
break;
default:
@@ -171,8 +162,8 @@
}
}
- final dynamic _json;
+ final Object _json;
/// Convert the object to a Json format.
- dynamic toJson() => _json;
+ Object toJson() => _json;
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/camera.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/camera.dart
index 10ea1e9..bdb0395 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/camera.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/camera.dart
@@ -4,8 +4,6 @@
import 'dart:ui' show hashValues, Offset;
-import 'package:meta/meta.dart' show required;
-
import 'types.dart';
/// The position of the map "camera", the view point from which the world is shown in the map view.
@@ -19,7 +17,7 @@
/// null.
const CameraPosition({
this.bearing = 0.0,
- @required this.target,
+ required this.target,
this.tilt = 0.0,
this.zoom = 0.0,
}) : assert(bearing != null),
@@ -63,7 +61,7 @@
/// Serializes [CameraPosition].
///
/// Mainly for internal use when calling [CameraUpdate.newCameraPosition].
- dynamic toMap() => <String, dynamic>{
+ Object toMap() => <String, Object>{
'bearing': bearing,
'target': target.toJson(),
'tilt': tilt,
@@ -73,23 +71,27 @@
/// Deserializes [CameraPosition] from a map.
///
/// Mainly for internal use.
- static CameraPosition fromMap(dynamic json) {
- if (json == null) {
+ static CameraPosition? fromMap(Object? json) {
+ if (json == null || !(json is Map<String, dynamic>)) {
+ return null;
+ }
+ final LatLng? target = LatLng.fromJson(json['target']);
+ if (target == null) {
return null;
}
return CameraPosition(
bearing: json['bearing'],
- target: LatLng.fromJson(json['target']),
+ target: target,
tilt: json['tilt'],
zoom: json['zoom'],
);
}
@override
- bool operator ==(dynamic other) {
+ bool operator ==(Object other) {
if (identical(this, other)) return true;
if (runtimeType != other.runtimeType) return false;
- final CameraPosition typedOther = other;
+ final CameraPosition typedOther = other as CameraPosition;
return bearing == typedOther.bearing &&
target == typedOther.target &&
tilt == typedOther.tilt &&
@@ -112,14 +114,14 @@
/// Returns a camera update that moves the camera to the specified position.
static CameraUpdate newCameraPosition(CameraPosition cameraPosition) {
return CameraUpdate._(
- <dynamic>['newCameraPosition', cameraPosition.toMap()],
+ <Object>['newCameraPosition', cameraPosition.toMap()],
);
}
/// Returns a camera update that moves the camera target to the specified
/// geographical location.
static CameraUpdate newLatLng(LatLng latLng) {
- return CameraUpdate._(<dynamic>['newLatLng', latLng.toJson()]);
+ return CameraUpdate._(<Object>['newLatLng', latLng.toJson()]);
}
/// Returns a camera update that transforms the camera so that the specified
@@ -127,7 +129,7 @@
/// possible zoom level. A non-zero [padding] insets the bounding box from the
/// map view's edges. The camera's new tilt and bearing will both be 0.0.
static CameraUpdate newLatLngBounds(LatLngBounds bounds, double padding) {
- return CameraUpdate._(<dynamic>[
+ return CameraUpdate._(<Object>[
'newLatLngBounds',
bounds.toJson(),
padding,
@@ -138,7 +140,7 @@
/// geographical location and zoom level.
static CameraUpdate newLatLngZoom(LatLng latLng, double zoom) {
return CameraUpdate._(
- <dynamic>['newLatLngZoom', latLng.toJson(), zoom],
+ <Object>['newLatLngZoom', latLng.toJson(), zoom],
);
}
@@ -150,18 +152,18 @@
/// 75 to the south of the current location, measured in screen coordinates.
static CameraUpdate scrollBy(double dx, double dy) {
return CameraUpdate._(
- <dynamic>['scrollBy', dx, dy],
+ <Object>['scrollBy', dx, dy],
);
}
/// Returns a camera update that modifies the camera zoom level by the
/// specified amount. The optional [focus] is a screen point whose underlying
/// geographical location should be invariant, if possible, by the movement.
- static CameraUpdate zoomBy(double amount, [Offset focus]) {
+ static CameraUpdate zoomBy(double amount, [Offset? focus]) {
if (focus == null) {
- return CameraUpdate._(<dynamic>['zoomBy', amount]);
+ return CameraUpdate._(<Object>['zoomBy', amount]);
} else {
- return CameraUpdate._(<dynamic>[
+ return CameraUpdate._(<Object>[
'zoomBy',
amount,
<double>[focus.dx, focus.dy],
@@ -174,7 +176,7 @@
///
/// Equivalent to the result of calling `zoomBy(1.0)`.
static CameraUpdate zoomIn() {
- return CameraUpdate._(<dynamic>['zoomIn']);
+ return CameraUpdate._(<Object>['zoomIn']);
}
/// Returns a camera update that zooms the camera out, bringing the camera
@@ -182,16 +184,16 @@
///
/// Equivalent to the result of calling `zoomBy(-1.0)`.
static CameraUpdate zoomOut() {
- return CameraUpdate._(<dynamic>['zoomOut']);
+ return CameraUpdate._(<Object>['zoomOut']);
}
/// Returns a camera update that sets the camera zoom level.
static CameraUpdate zoomTo(double zoom) {
- return CameraUpdate._(<dynamic>['zoomTo', zoom]);
+ return CameraUpdate._(<Object>['zoomTo', zoom]);
}
- final dynamic _json;
+ final Object _json;
/// Converts this object to something serializable in JSON.
- dynamic toJson() => _json;
+ Object toJson() => _json;
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/cap.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/cap.dart
index 68bf14c..c88923a 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/cap.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/cap.dart
@@ -17,16 +17,16 @@
///
/// This is the default cap type at start and end vertices of Polylines with
/// solid stroke pattern.
- static const Cap buttCap = Cap._(<dynamic>['buttCap']);
+ static const Cap buttCap = Cap._(<Object>['buttCap']);
/// Cap that is a semicircle with radius equal to half the stroke width,
/// centered at the start or end vertex of a [Polyline] with solid stroke
/// pattern.
- static const Cap roundCap = Cap._(<dynamic>['roundCap']);
+ static const Cap roundCap = Cap._(<Object>['roundCap']);
/// Cap that is squared off after extending half the stroke width beyond the
/// start or end vertex of a [Polyline] with solid stroke pattern.
- static const Cap squareCap = Cap._(<dynamic>['squareCap']);
+ static const Cap squareCap = Cap._(<Object>['squareCap']);
/// Constructs a new CustomCap with a bitmap overlay centered at the start or
/// end vertex of a [Polyline], orientated according to the direction of the line's
@@ -45,11 +45,11 @@
}) {
assert(bitmapDescriptor != null);
assert(refWidth > 0.0);
- return Cap._(<dynamic>['customCap', bitmapDescriptor.toJson(), refWidth]);
+ return Cap._(<Object>['customCap', bitmapDescriptor.toJson(), refWidth]);
}
- final dynamic _json;
+ final Object _json;
/// Converts this object to something serializable in JSON.
- dynamic toJson() => _json;
+ Object toJson() => _json;
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle.dart
index d1418a4..e3198df 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle.dart
@@ -4,7 +4,7 @@
import 'package:flutter/foundation.dart' show VoidCallback;
import 'package:flutter/material.dart' show Color, Colors;
-import 'package:meta/meta.dart' show immutable, required;
+import 'package:meta/meta.dart' show immutable;
import 'types.dart';
@@ -12,36 +12,17 @@
///
/// This does not have to be globally unique, only unique among the list.
@immutable
-class CircleId {
+class CircleId extends MapsObjectId<Circle> {
/// Creates an immutable identifier for a [Circle].
- CircleId(this.value) : assert(value != null);
-
- /// value of the [CircleId].
- final String value;
-
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- if (other.runtimeType != runtimeType) return false;
- final CircleId typedOther = other;
- return value == typedOther.value;
- }
-
- @override
- int get hashCode => value.hashCode;
-
- @override
- String toString() {
- return 'CircleId{value: $value}';
- }
+ CircleId(String value) : super(value);
}
/// Draws a circle on the map.
@immutable
-class Circle {
+class Circle implements MapsObject<Circle> {
/// Creates an immutable representation of a [Circle] to draw on [GoogleMap].
const Circle({
- @required this.circleId,
+ required this.circleId,
this.consumeTapEvents = false,
this.fillColor = Colors.transparent,
this.center = const LatLng(0.0, 0.0),
@@ -56,6 +37,9 @@
/// Uniquely identifies a [Circle].
final CircleId circleId;
+ @override
+ CircleId get mapsId => circleId;
+
/// True if the [Circle] consumes tap events.
///
/// If this is false, [onTap] callback will not be triggered.
@@ -91,20 +75,20 @@
final int zIndex;
/// Callbacks to receive tap events for circle placed on this map.
- final VoidCallback onTap;
+ final VoidCallback? onTap;
/// Creates a new [Circle] object whose values are the same as this instance,
/// unless overwritten by the specified parameters.
Circle copyWith({
- bool consumeTapEventsParam,
- Color fillColorParam,
- LatLng centerParam,
- double radiusParam,
- Color strokeColorParam,
- int strokeWidthParam,
- bool visibleParam,
- int zIndexParam,
- VoidCallback onTapParam,
+ bool? consumeTapEventsParam,
+ Color? fillColorParam,
+ LatLng? centerParam,
+ double? radiusParam,
+ Color? strokeColorParam,
+ int? strokeWidthParam,
+ bool? visibleParam,
+ int? zIndexParam,
+ VoidCallback? onTapParam,
}) {
return Circle(
circleId: circleId,
@@ -124,10 +108,10 @@
Circle clone() => copyWith();
/// Converts this object to something serializable in JSON.
- dynamic toJson() {
- final Map<String, dynamic> json = <String, dynamic>{};
+ Object toJson() {
+ final Map<String, Object> json = <String, Object>{};
- void addIfPresent(String fieldName, dynamic value) {
+ void addIfPresent(String fieldName, Object? value) {
if (value != null) {
json[fieldName] = value;
}
@@ -150,7 +134,7 @@
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other.runtimeType != runtimeType) return false;
- final Circle typedOther = other;
+ final Circle typedOther = other as Circle;
return circleId == typedOther.circleId &&
consumeTapEvents == typedOther.consumeTapEvents &&
fillColor == typedOther.fillColor &&
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle_updates.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle_updates.dart
index 6f49442..a0b064b 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle_updates.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle_updates.dart
@@ -2,109 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:ui' show hashValues;
-
-import 'package:flutter/foundation.dart' show setEquals;
-
import 'types.dart';
-import 'utils/circle.dart';
/// [Circle] update events to be applied to the [GoogleMap].
///
/// Used in [GoogleMapController] when the map is updated.
// (Do not re-export)
-class CircleUpdates {
+class CircleUpdates extends MapsObjectUpdates<Circle> {
/// Computes [CircleUpdates] given previous and current [Circle]s.
- CircleUpdates.from(Set<Circle> previous, Set<Circle> current) {
- if (previous == null) {
- previous = Set<Circle>.identity();
- }
-
- if (current == null) {
- current = Set<Circle>.identity();
- }
-
- final Map<CircleId, Circle> previousCircles = keyByCircleId(previous);
- final Map<CircleId, Circle> currentCircles = keyByCircleId(current);
-
- final Set<CircleId> prevCircleIds = previousCircles.keys.toSet();
- final Set<CircleId> currentCircleIds = currentCircles.keys.toSet();
-
- Circle idToCurrentCircle(CircleId id) {
- return currentCircles[id];
- }
-
- final Set<CircleId> _circleIdsToRemove =
- prevCircleIds.difference(currentCircleIds);
-
- final Set<Circle> _circlesToAdd = currentCircleIds
- .difference(prevCircleIds)
- .map(idToCurrentCircle)
- .toSet();
-
- /// Returns `true` if [current] is not equals to previous one with the
- /// same id.
- bool hasChanged(Circle current) {
- final Circle previous = previousCircles[current.circleId];
- return current != previous;
- }
-
- final Set<Circle> _circlesToChange = currentCircleIds
- .intersection(prevCircleIds)
- .map(idToCurrentCircle)
- .where(hasChanged)
- .toSet();
-
- circlesToAdd = _circlesToAdd;
- circleIdsToRemove = _circleIdsToRemove;
- circlesToChange = _circlesToChange;
- }
+ CircleUpdates.from(Set<Circle> previous, Set<Circle> current)
+ : super.from(previous, current, objectName: 'circle');
/// Set of Circles to be added in this update.
- Set<Circle> circlesToAdd;
+ Set<Circle> get circlesToAdd => objectsToAdd;
/// Set of CircleIds to be removed in this update.
- Set<CircleId> circleIdsToRemove;
+ Set<CircleId> get circleIdsToRemove => objectIdsToRemove.cast<CircleId>();
/// Set of Circles to be changed in this update.
- Set<Circle> circlesToChange;
-
- /// Converts this object to something serializable in JSON.
- Map<String, dynamic> toJson() {
- final Map<String, dynamic> updateMap = <String, dynamic>{};
-
- void addIfNonNull(String fieldName, dynamic value) {
- if (value != null) {
- updateMap[fieldName] = value;
- }
- }
-
- addIfNonNull('circlesToAdd', serializeCircleSet(circlesToAdd));
- addIfNonNull('circlesToChange', serializeCircleSet(circlesToChange));
- addIfNonNull('circleIdsToRemove',
- circleIdsToRemove.map<dynamic>((CircleId m) => m.value).toList());
-
- return updateMap;
- }
-
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- if (other.runtimeType != runtimeType) return false;
- final CircleUpdates typedOther = other;
- return setEquals(circlesToAdd, typedOther.circlesToAdd) &&
- setEquals(circleIdsToRemove, typedOther.circleIdsToRemove) &&
- setEquals(circlesToChange, typedOther.circlesToChange);
- }
-
- @override
- int get hashCode =>
- hashValues(circlesToAdd, circleIdsToRemove, circlesToChange);
-
- @override
- String toString() {
- return '_CircleUpdates{circlesToAdd: $circlesToAdd, '
- 'circleIdsToRemove: $circleIdsToRemove, '
- 'circlesToChange: $circlesToChange}';
- }
+ Set<Circle> get circlesToChange => objectsToChange;
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/location.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/location.dart
index 6b76a6d..a719f0b 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/location.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/location.dart
@@ -29,16 +29,18 @@
final double longitude;
/// Converts this object to something serializable in JSON.
- dynamic toJson() {
+ Object toJson() {
return <double>[latitude, longitude];
}
/// Initialize a LatLng from an \[lat, lng\] array.
- static LatLng fromJson(dynamic json) {
+ static LatLng? fromJson(Object? json) {
if (json == null) {
return null;
}
- return LatLng(json[0], json[1]);
+ assert(json is List && json.length == 2);
+ final list = json as List;
+ return LatLng(list[0], list[1]);
}
@override
@@ -66,7 +68,7 @@
///
/// The latitude of the southwest corner cannot be larger than the
/// latitude of the northeast corner.
- LatLngBounds({@required this.southwest, @required this.northeast})
+ LatLngBounds({required this.southwest, required this.northeast})
: assert(southwest != null),
assert(northeast != null),
assert(southwest.latitude <= northeast.latitude);
@@ -78,8 +80,8 @@
final LatLng northeast;
/// Converts this object to something serializable in JSON.
- dynamic toJson() {
- return <dynamic>[southwest.toJson(), northeast.toJson()];
+ Object toJson() {
+ return <Object>[southwest.toJson(), northeast.toJson()];
}
/// Returns whether this rectangle contains the given [LatLng].
@@ -102,13 +104,15 @@
/// Converts a list to [LatLngBounds].
@visibleForTesting
- static LatLngBounds fromList(dynamic json) {
+ static LatLngBounds? fromList(Object? json) {
if (json == null) {
return null;
}
+ assert(json is List && json.length == 2);
+ final list = json as List;
return LatLngBounds(
- southwest: LatLng.fromJson(json[0]),
- northeast: LatLng.fromJson(json[1]),
+ southwest: LatLng.fromJson(list[0])!,
+ northeast: LatLng.fromJson(list[1])!,
);
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/maps_object.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/maps_object.dart
new file mode 100644
index 0000000..545d462
--- /dev/null
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/maps_object.dart
@@ -0,0 +1,49 @@
+// Copyright 2019 The Chromium 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/foundation.dart' show objectRuntimeType;
+import 'package:meta/meta.dart' show immutable;
+
+/// Uniquely identifies object an among [GoogleMap] collections of a specific
+/// type.
+///
+/// This does not have to be globally unique, only unique among the collection.
+@immutable
+class MapsObjectId<T> {
+ /// Creates an immutable object representing a [T] among [GoogleMap] Ts.
+ ///
+ /// An [AssertionError] will be thrown if [value] is null.
+ MapsObjectId(this.value) : assert(value != null);
+
+ /// The value of the id.
+ final String value;
+
+ @override
+ bool operator ==(Object other) {
+ if (identical(this, other)) return true;
+ if (other.runtimeType != runtimeType) return false;
+ final MapsObjectId<T> typedOther = other as MapsObjectId<T>;
+ return value == typedOther.value;
+ }
+
+ @override
+ int get hashCode => value.hashCode;
+
+ @override
+ String toString() {
+ return '${objectRuntimeType(this, 'MapsObjectId')}($value)';
+ }
+}
+
+/// A common interface for maps types.
+abstract class MapsObject<T> {
+ /// A identifier for this object.
+ MapsObjectId<T> get mapsId;
+
+ /// Returns a duplicate of this object.
+ T clone();
+
+ /// Converts this object to something serializable in JSON.
+ Object toJson();
+}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/maps_object_updates.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/maps_object_updates.dart
new file mode 100644
index 0000000..01cf967
--- /dev/null
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/maps_object_updates.dart
@@ -0,0 +1,126 @@
+// Copyright 2018 The Chromium 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:ui' show hashValues, hashList;
+
+import 'package:flutter/foundation.dart' show objectRuntimeType, setEquals;
+
+import 'maps_object.dart';
+import 'utils/maps_object.dart';
+
+/// Update specification for a set of objects.
+class MapsObjectUpdates<T extends MapsObject> {
+ /// Computes updates given previous and current object sets.
+ ///
+ /// [objectName] is the prefix to use when serializing the updates into a JSON
+ /// dictionary. E.g., 'circle' will give 'circlesToAdd', 'circlesToUpdate',
+ /// 'circleIdsToRemove'.
+ MapsObjectUpdates.from(
+ Set<T> previous,
+ Set<T> current, {
+ required this.objectName,
+ }) {
+ final Map<MapsObjectId<T>, T> previousObjects = keyByMapsObjectId(previous);
+ final Map<MapsObjectId<T>, T> currentObjects = keyByMapsObjectId(current);
+
+ final Set<MapsObjectId<T>> previousObjectIds = previousObjects.keys.toSet();
+ final Set<MapsObjectId<T>> currentObjectIds = currentObjects.keys.toSet();
+
+ /// Maps an ID back to a [T] in [currentObjects].
+ ///
+ /// It is a programming error to call this with an ID that is not guaranteed
+ /// to be in [currentObjects].
+ T _idToCurrentObject(MapsObjectId<T> id) {
+ return currentObjects[id]!;
+ }
+
+ _objectIdsToRemove = previousObjectIds.difference(currentObjectIds);
+
+ _objectsToAdd = currentObjectIds
+ .difference(previousObjectIds)
+ .map(_idToCurrentObject)
+ .toSet();
+
+ // Returns `true` if [current] is not equals to previous one with the
+ // same id.
+ bool hasChanged(T current) {
+ final T? previous = previousObjects[current.mapsId as MapsObjectId<T>];
+ return current != previous;
+ }
+
+ _objectsToChange = currentObjectIds
+ .intersection(previousObjectIds)
+ .map(_idToCurrentObject)
+ .where(hasChanged)
+ .toSet();
+ }
+
+ /// The name of the objects being updated, for use in serialization.
+ final String objectName;
+
+ /// Set of objects to be added in this update.
+ Set<T> get objectsToAdd {
+ return _objectsToAdd;
+ }
+
+ late Set<T> _objectsToAdd;
+
+ /// Set of objects to be removed in this update.
+ Set<MapsObjectId<T>> get objectIdsToRemove {
+ return _objectIdsToRemove;
+ }
+
+ late Set<MapsObjectId<T>> _objectIdsToRemove;
+
+ /// Set of objects to be changed in this update.
+ Set<T> get objectsToChange {
+ return _objectsToChange;
+ }
+
+ late Set<T> _objectsToChange;
+
+ /// Converts this object to JSON.
+ Object toJson() {
+ final Map<String, Object> updateMap = <String, Object>{};
+
+ void addIfNonNull(String fieldName, Object? value) {
+ if (value != null) {
+ updateMap[fieldName] = value;
+ }
+ }
+
+ addIfNonNull('${objectName}sToAdd', serializeMapsObjectSet(_objectsToAdd));
+ addIfNonNull(
+ '${objectName}sToChange', serializeMapsObjectSet(_objectsToChange));
+ addIfNonNull(
+ '${objectName}IdsToRemove',
+ _objectIdsToRemove
+ .map<String>((MapsObjectId<T> m) => m.value)
+ .toList());
+
+ return updateMap;
+ }
+
+ @override
+ bool operator ==(Object other) {
+ if (other.runtimeType != runtimeType) {
+ return false;
+ }
+ return other is MapsObjectUpdates &&
+ setEquals(_objectsToAdd, other._objectsToAdd) &&
+ setEquals(_objectIdsToRemove, other._objectIdsToRemove) &&
+ setEquals(_objectsToChange, other._objectsToChange);
+ }
+
+ @override
+ int get hashCode => hashValues(hashList(_objectsToAdd),
+ hashList(_objectIdsToRemove), hashList(_objectsToChange));
+
+ @override
+ String toString() {
+ return '${objectRuntimeType(this, 'MapsObjectUpdates')}(add: $objectsToAdd, '
+ 'remove: $objectIdsToRemove, '
+ 'change: $objectsToChange)';
+ }
+}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker.dart
index 9b57f96..15351d5 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker.dart
@@ -5,15 +5,12 @@
import 'dart:ui' show hashValues, Offset;
import 'package:flutter/foundation.dart' show ValueChanged, VoidCallback;
-import 'package:meta/meta.dart' show immutable, required;
+import 'package:meta/meta.dart' show immutable;
import 'types.dart';
-dynamic _offsetToJson(Offset offset) {
- if (offset == null) {
- return null;
- }
- return <dynamic>[offset.dx, offset.dy];
+Object _offsetToJson(Offset offset) {
+ return <Object>[offset.dx, offset.dy];
}
/// Text labels for a [Marker] info window.
@@ -32,12 +29,12 @@
/// Text displayed in an info window when the user taps the marker.
///
/// A null value means no title.
- final String title;
+ final String? title;
/// Additional text displayed below the [title].
///
/// A null value means no additional text.
- final String snippet;
+ final String? snippet;
/// The icon image point that will be the anchor of the info window when
/// displayed.
@@ -48,15 +45,15 @@
final Offset anchor;
/// onTap callback for this [InfoWindow].
- final VoidCallback onTap;
+ final VoidCallback? onTap;
/// Creates a new [InfoWindow] object whose values are the same as this instance,
/// unless overwritten by the specified parameters.
InfoWindow copyWith({
- String titleParam,
- String snippetParam,
- Offset anchorParam,
- VoidCallback onTapParam,
+ String? titleParam,
+ String? snippetParam,
+ Offset? anchorParam,
+ VoidCallback? onTapParam,
}) {
return InfoWindow(
title: titleParam ?? title,
@@ -66,10 +63,10 @@
);
}
- dynamic _toJson() {
- final Map<String, dynamic> json = <String, dynamic>{};
+ Object _toJson() {
+ final Map<String, Object> json = <String, Object>{};
- void addIfPresent(String fieldName, dynamic value) {
+ void addIfPresent(String fieldName, Object? value) {
if (value != null) {
json[fieldName] = value;
}
@@ -86,7 +83,7 @@
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other.runtimeType != runtimeType) return false;
- final InfoWindow typedOther = other;
+ final InfoWindow typedOther = other as InfoWindow;
return title == typedOther.title &&
snippet == typedOther.snippet &&
anchor == typedOther.anchor;
@@ -105,28 +102,9 @@
///
/// This does not have to be globally unique, only unique among the list.
@immutable
-class MarkerId {
+class MarkerId extends MapsObjectId<Marker> {
/// Creates an immutable identifier for a [Marker].
- MarkerId(this.value) : assert(value != null);
-
- /// value of the [MarkerId].
- final String value;
-
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- if (other.runtimeType != runtimeType) return false;
- final MarkerId typedOther = other;
- return value == typedOther.value;
- }
-
- @override
- int get hashCode => value.hashCode;
-
- @override
- String toString() {
- return 'MarkerId{value: $value}';
- }
+ MarkerId(String value) : super(value);
}
/// Marks a geographical location on the map.
@@ -135,7 +113,7 @@
/// the map's surface; that is, it will not necessarily change orientation
/// due to map rotations, tilting, or zooming.
@immutable
-class Marker {
+class Marker implements MapsObject {
/// Creates a set of marker configuration options.
///
/// Default marker options.
@@ -156,7 +134,7 @@
/// * reports [onTap] events
/// * reports [onDragEnd] events
const Marker({
- @required this.markerId,
+ required this.markerId,
this.alpha = 1.0,
this.anchor = const Offset(0.5, 1.0),
this.consumeTapEvents = false,
@@ -175,6 +153,9 @@
/// Uniquely identifies a [Marker].
final MarkerId markerId;
+ @override
+ MarkerId get mapsId => markerId;
+
/// The opacity of the marker, between 0.0 and 1.0 inclusive.
///
/// 0.0 means fully transparent, 1.0 means fully opaque.
@@ -224,27 +205,27 @@
final double zIndex;
/// Callbacks to receive tap events for markers placed on this map.
- final VoidCallback onTap;
+ final VoidCallback? onTap;
/// Signature reporting the new [LatLng] at the end of a drag event.
- final ValueChanged<LatLng> onDragEnd;
+ final ValueChanged<LatLng>? onDragEnd;
/// Creates a new [Marker] object whose values are the same as this instance,
/// unless overwritten by the specified parameters.
Marker copyWith({
- double alphaParam,
- Offset anchorParam,
- bool consumeTapEventsParam,
- bool draggableParam,
- bool flatParam,
- BitmapDescriptor iconParam,
- InfoWindow infoWindowParam,
- LatLng positionParam,
- double rotationParam,
- bool visibleParam,
- double zIndexParam,
- VoidCallback onTapParam,
- ValueChanged<LatLng> onDragEndParam,
+ double? alphaParam,
+ Offset? anchorParam,
+ bool? consumeTapEventsParam,
+ bool? draggableParam,
+ bool? flatParam,
+ BitmapDescriptor? iconParam,
+ InfoWindow? infoWindowParam,
+ LatLng? positionParam,
+ double? rotationParam,
+ bool? visibleParam,
+ double? zIndexParam,
+ VoidCallback? onTapParam,
+ ValueChanged<LatLng>? onDragEndParam,
}) {
return Marker(
markerId: markerId,
@@ -268,10 +249,10 @@
Marker clone() => copyWith();
/// Converts this object to something serializable in JSON.
- Map<String, dynamic> toJson() {
- final Map<String, dynamic> json = <String, dynamic>{};
+ Object toJson() {
+ final Map<String, Object> json = <String, Object>{};
- void addIfPresent(String fieldName, dynamic value) {
+ void addIfPresent(String fieldName, Object? value) {
if (value != null) {
json[fieldName] = value;
}
@@ -283,9 +264,9 @@
addIfPresent('consumeTapEvents', consumeTapEvents);
addIfPresent('draggable', draggable);
addIfPresent('flat', flat);
- addIfPresent('icon', icon?.toJson());
- addIfPresent('infoWindow', infoWindow?._toJson());
- addIfPresent('position', position?.toJson());
+ addIfPresent('icon', icon.toJson());
+ addIfPresent('infoWindow', infoWindow._toJson());
+ addIfPresent('position', position.toJson());
addIfPresent('rotation', rotation);
addIfPresent('visible', visible);
addIfPresent('zIndex', zIndex);
@@ -296,7 +277,7 @@
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other.runtimeType != runtimeType) return false;
- final Marker typedOther = other;
+ final Marker typedOther = other as Marker;
return markerId == typedOther.markerId &&
alpha == typedOther.alpha &&
anchor == typedOther.anchor &&
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker_updates.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker_updates.dart
index bb6ea88..9c96ab6 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker_updates.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker_updates.dart
@@ -2,109 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:ui' show hashValues;
-
-import 'package:flutter/foundation.dart' show setEquals;
-
import 'types.dart';
-import 'utils/marker.dart';
/// [Marker] update events to be applied to the [GoogleMap].
///
/// Used in [GoogleMapController] when the map is updated.
// (Do not re-export)
-class MarkerUpdates {
+class MarkerUpdates extends MapsObjectUpdates<Marker> {
/// Computes [MarkerUpdates] given previous and current [Marker]s.
- MarkerUpdates.from(Set<Marker> previous, Set<Marker> current) {
- if (previous == null) {
- previous = Set<Marker>.identity();
- }
-
- if (current == null) {
- current = Set<Marker>.identity();
- }
-
- final Map<MarkerId, Marker> previousMarkers = keyByMarkerId(previous);
- final Map<MarkerId, Marker> currentMarkers = keyByMarkerId(current);
-
- final Set<MarkerId> prevMarkerIds = previousMarkers.keys.toSet();
- final Set<MarkerId> currentMarkerIds = currentMarkers.keys.toSet();
-
- Marker idToCurrentMarker(MarkerId id) {
- return currentMarkers[id];
- }
-
- final Set<MarkerId> _markerIdsToRemove =
- prevMarkerIds.difference(currentMarkerIds);
-
- final Set<Marker> _markersToAdd = currentMarkerIds
- .difference(prevMarkerIds)
- .map(idToCurrentMarker)
- .toSet();
-
- /// Returns `true` if [current] is not equals to previous one with the
- /// same id.
- bool hasChanged(Marker current) {
- final Marker previous = previousMarkers[current.markerId];
- return current != previous;
- }
-
- final Set<Marker> _markersToChange = currentMarkerIds
- .intersection(prevMarkerIds)
- .map(idToCurrentMarker)
- .where(hasChanged)
- .toSet();
-
- markersToAdd = _markersToAdd;
- markerIdsToRemove = _markerIdsToRemove;
- markersToChange = _markersToChange;
- }
+ MarkerUpdates.from(Set<Marker> previous, Set<Marker> current)
+ : super.from(previous, current, objectName: 'marker');
/// Set of Markers to be added in this update.
- Set<Marker> markersToAdd;
+ Set<Marker> get markersToAdd => objectsToAdd;
/// Set of MarkerIds to be removed in this update.
- Set<MarkerId> markerIdsToRemove;
+ Set<MarkerId> get markerIdsToRemove => objectIdsToRemove.cast<MarkerId>();
/// Set of Markers to be changed in this update.
- Set<Marker> markersToChange;
-
- /// Converts this object to something serializable in JSON.
- Map<String, dynamic> toJson() {
- final Map<String, dynamic> updateMap = <String, dynamic>{};
-
- void addIfNonNull(String fieldName, dynamic value) {
- if (value != null) {
- updateMap[fieldName] = value;
- }
- }
-
- addIfNonNull('markersToAdd', serializeMarkerSet(markersToAdd));
- addIfNonNull('markersToChange', serializeMarkerSet(markersToChange));
- addIfNonNull('markerIdsToRemove',
- markerIdsToRemove.map<dynamic>((MarkerId m) => m.value).toList());
-
- return updateMap;
- }
-
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- if (other.runtimeType != runtimeType) return false;
- final MarkerUpdates typedOther = other;
- return setEquals(markersToAdd, typedOther.markersToAdd) &&
- setEquals(markerIdsToRemove, typedOther.markerIdsToRemove) &&
- setEquals(markersToChange, typedOther.markersToChange);
- }
-
- @override
- int get hashCode =>
- hashValues(markersToAdd, markerIdsToRemove, markersToChange);
-
- @override
- String toString() {
- return '_MarkerUpdates{markersToAdd: $markersToAdd, '
- 'markerIdsToRemove: $markerIdsToRemove, '
- 'markersToChange: $markersToChange}';
- }
+ Set<Marker> get markersToChange => objectsToChange;
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/pattern_item.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/pattern_item.dart
index 28c7ce9..f1cd7f4 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/pattern_item.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/pattern_item.dart
@@ -10,14 +10,14 @@
const PatternItem._(this._json);
/// A dot used in the stroke pattern for a [Polyline].
- static const PatternItem dot = PatternItem._(<dynamic>['dot']);
+ static const PatternItem dot = PatternItem._(<Object>['dot']);
/// A dash used in the stroke pattern for a [Polyline].
///
/// [length] has to be non-negative.
static PatternItem dash(double length) {
assert(length >= 0.0);
- return PatternItem._(<dynamic>['dash', length]);
+ return PatternItem._(<Object>['dash', length]);
}
/// A gap used in the stroke pattern for a [Polyline].
@@ -25,11 +25,11 @@
/// [length] has to be non-negative.
static PatternItem gap(double length) {
assert(length >= 0.0);
- return PatternItem._(<dynamic>['gap', length]);
+ return PatternItem._(<Object>['gap', length]);
}
- final dynamic _json;
+ final Object _json;
/// Converts this object to something serializable in JSON.
- dynamic toJson() => _json;
+ Object toJson() => _json;
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon.dart
index 96b3915..4e5e9bf 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon.dart
@@ -5,7 +5,7 @@
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart' show listEquals, VoidCallback;
import 'package:flutter/material.dart' show Color, Colors;
-import 'package:meta/meta.dart' show immutable, required;
+import 'package:meta/meta.dart' show immutable;
import 'types.dart';
@@ -13,36 +13,17 @@
///
/// This does not have to be globally unique, only unique among the list.
@immutable
-class PolygonId {
+class PolygonId extends MapsObjectId<Polygon> {
/// Creates an immutable identifier for a [Polygon].
- PolygonId(this.value) : assert(value != null);
-
- /// value of the [PolygonId].
- final String value;
-
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- if (other.runtimeType != runtimeType) return false;
- final PolygonId typedOther = other;
- return value == typedOther.value;
- }
-
- @override
- int get hashCode => value.hashCode;
-
- @override
- String toString() {
- return 'PolygonId{value: $value}';
- }
+ PolygonId(String value) : super(value);
}
/// Draws a polygon through geographical locations on the map.
@immutable
-class Polygon {
+class Polygon implements MapsObject {
/// Creates an immutable representation of a polygon through geographical locations on the map.
const Polygon({
- @required this.polygonId,
+ required this.polygonId,
this.consumeTapEvents = false,
this.fillColor = Colors.black,
this.geodesic = false,
@@ -58,6 +39,9 @@
/// Uniquely identifies a [Polygon].
final PolygonId polygonId;
+ @override
+ PolygonId get mapsId => polygonId;
+
/// True if the [Polygon] consumes tap events.
///
/// If this is false, [onTap] callback will not be triggered.
@@ -107,21 +91,21 @@
final int zIndex;
/// Callbacks to receive tap events for polygon placed on this map.
- final VoidCallback onTap;
+ final VoidCallback? onTap;
/// Creates a new [Polygon] object whose values are the same as this instance,
/// unless overwritten by the specified parameters.
Polygon copyWith({
- bool consumeTapEventsParam,
- Color fillColorParam,
- bool geodesicParam,
- List<LatLng> pointsParam,
- List<List<LatLng>> holesParam,
- Color strokeColorParam,
- int strokeWidthParam,
- bool visibleParam,
- int zIndexParam,
- VoidCallback onTapParam,
+ bool? consumeTapEventsParam,
+ Color? fillColorParam,
+ bool? geodesicParam,
+ List<LatLng>? pointsParam,
+ List<List<LatLng>>? holesParam,
+ Color? strokeColorParam,
+ int? strokeWidthParam,
+ bool? visibleParam,
+ int? zIndexParam,
+ VoidCallback? onTapParam,
}) {
return Polygon(
polygonId: polygonId,
@@ -144,10 +128,10 @@
}
/// Converts this object to something serializable in JSON.
- dynamic toJson() {
- final Map<String, dynamic> json = <String, dynamic>{};
+ Object toJson() {
+ final Map<String, Object> json = <String, Object>{};
- void addIfPresent(String fieldName, dynamic value) {
+ void addIfPresent(String fieldName, Object? value) {
if (value != null) {
json[fieldName] = value;
}
@@ -177,7 +161,7 @@
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other.runtimeType != runtimeType) return false;
- final Polygon typedOther = other;
+ final Polygon typedOther = other as Polygon;
return polygonId == typedOther.polygonId &&
consumeTapEvents == typedOther.consumeTapEvents &&
fillColor == typedOther.fillColor &&
@@ -193,18 +177,18 @@
@override
int get hashCode => polygonId.hashCode;
- dynamic _pointsToJson() {
- final List<dynamic> result = <dynamic>[];
+ Object _pointsToJson() {
+ final List<Object> result = <Object>[];
for (final LatLng point in points) {
result.add(point.toJson());
}
return result;
}
- List<List<dynamic>> _holesToJson() {
- final List<List<dynamic>> result = <List<dynamic>>[];
+ List<List<Object>> _holesToJson() {
+ final List<List<Object>> result = <List<Object>>[];
for (final List<LatLng> hole in holes) {
- final List<dynamic> jsonHole = <dynamic>[];
+ final List<Object> jsonHole = <Object>[];
for (final LatLng point in hole) {
jsonHole.add(point.toJson());
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon_updates.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon_updates.dart
index cc8b8e2..29b74ae 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon_updates.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon_updates.dart
@@ -2,109 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:ui' show hashValues;
-
-import 'package:flutter/foundation.dart' show setEquals;
-
import 'types.dart';
-import 'utils/polygon.dart';
/// [Polygon] update events to be applied to the [GoogleMap].
///
/// Used in [GoogleMapController] when the map is updated.
// (Do not re-export)
-class PolygonUpdates {
+class PolygonUpdates extends MapsObjectUpdates<Polygon> {
/// Computes [PolygonUpdates] given previous and current [Polygon]s.
- PolygonUpdates.from(Set<Polygon> previous, Set<Polygon> current) {
- if (previous == null) {
- previous = Set<Polygon>.identity();
- }
-
- if (current == null) {
- current = Set<Polygon>.identity();
- }
-
- final Map<PolygonId, Polygon> previousPolygons = keyByPolygonId(previous);
- final Map<PolygonId, Polygon> currentPolygons = keyByPolygonId(current);
-
- final Set<PolygonId> prevPolygonIds = previousPolygons.keys.toSet();
- final Set<PolygonId> currentPolygonIds = currentPolygons.keys.toSet();
-
- Polygon idToCurrentPolygon(PolygonId id) {
- return currentPolygons[id];
- }
-
- final Set<PolygonId> _polygonIdsToRemove =
- prevPolygonIds.difference(currentPolygonIds);
-
- final Set<Polygon> _polygonsToAdd = currentPolygonIds
- .difference(prevPolygonIds)
- .map(idToCurrentPolygon)
- .toSet();
-
- /// Returns `true` if [current] is not equals to previous one with the
- /// same id.
- bool hasChanged(Polygon current) {
- final Polygon previous = previousPolygons[current.polygonId];
- return current != previous;
- }
-
- final Set<Polygon> _polygonsToChange = currentPolygonIds
- .intersection(prevPolygonIds)
- .map(idToCurrentPolygon)
- .where(hasChanged)
- .toSet();
-
- polygonsToAdd = _polygonsToAdd;
- polygonIdsToRemove = _polygonIdsToRemove;
- polygonsToChange = _polygonsToChange;
- }
+ PolygonUpdates.from(Set<Polygon> previous, Set<Polygon> current)
+ : super.from(previous, current, objectName: 'polygon');
/// Set of Polygons to be added in this update.
- Set<Polygon> polygonsToAdd;
+ Set<Polygon> get polygonsToAdd => objectsToAdd;
/// Set of PolygonIds to be removed in this update.
- Set<PolygonId> polygonIdsToRemove;
+ Set<PolygonId> get polygonIdsToRemove => objectIdsToRemove.cast<PolygonId>();
/// Set of Polygons to be changed in this update.
- Set<Polygon> polygonsToChange;
-
- /// Converts this object to something serializable in JSON.
- Map<String, dynamic> toJson() {
- final Map<String, dynamic> updateMap = <String, dynamic>{};
-
- void addIfNonNull(String fieldName, dynamic value) {
- if (value != null) {
- updateMap[fieldName] = value;
- }
- }
-
- addIfNonNull('polygonsToAdd', serializePolygonSet(polygonsToAdd));
- addIfNonNull('polygonsToChange', serializePolygonSet(polygonsToChange));
- addIfNonNull('polygonIdsToRemove',
- polygonIdsToRemove.map<dynamic>((PolygonId m) => m.value).toList());
-
- return updateMap;
- }
-
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- if (other.runtimeType != runtimeType) return false;
- final PolygonUpdates typedOther = other;
- return setEquals(polygonsToAdd, typedOther.polygonsToAdd) &&
- setEquals(polygonIdsToRemove, typedOther.polygonIdsToRemove) &&
- setEquals(polygonsToChange, typedOther.polygonsToChange);
- }
-
- @override
- int get hashCode =>
- hashValues(polygonsToAdd, polygonIdsToRemove, polygonsToChange);
-
- @override
- String toString() {
- return '_PolygonUpdates{polygonsToAdd: $polygonsToAdd, '
- 'polygonIdsToRemove: $polygonIdsToRemove, '
- 'polygonsToChange: $polygonsToChange}';
- }
+ Set<Polygon> get polygonsToChange => objectsToChange;
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline.dart
index ae5c3b9..3f87395 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline.dart
@@ -4,7 +4,7 @@
import 'package:flutter/foundation.dart' show listEquals, VoidCallback;
import 'package:flutter/material.dart' show Color, Colors;
-import 'package:meta/meta.dart' show immutable, required;
+import 'package:meta/meta.dart' show immutable;
import 'types.dart';
@@ -12,38 +12,19 @@
///
/// This does not have to be globally unique, only unique among the list.
@immutable
-class PolylineId {
+class PolylineId extends MapsObjectId<Polyline> {
/// Creates an immutable object representing a [PolylineId] among [GoogleMap] polylines.
///
/// An [AssertionError] will be thrown if [value] is null.
- PolylineId(this.value) : assert(value != null);
-
- /// value of the [PolylineId].
- final String value;
-
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- if (other.runtimeType != runtimeType) return false;
- final PolylineId typedOther = other;
- return value == typedOther.value;
- }
-
- @override
- int get hashCode => value.hashCode;
-
- @override
- String toString() {
- return 'PolylineId{value: $value}';
- }
+ PolylineId(String value) : super(value);
}
/// Draws a line through geographical locations on the map.
@immutable
-class Polyline {
+class Polyline implements MapsObject {
/// Creates an immutable object representing a line drawn through geographical locations on the map.
const Polyline({
- @required this.polylineId,
+ required this.polylineId,
this.consumeTapEvents = false,
this.color = Colors.black,
this.endCap = Cap.buttCap,
@@ -61,6 +42,9 @@
/// Uniquely identifies a [Polyline].
final PolylineId polylineId;
+ @override
+ PolylineId get mapsId => polylineId;
+
/// True if the [Polyline] consumes tap events.
///
/// If this is false, [onTap] callback will not be triggered.
@@ -129,23 +113,23 @@
final int zIndex;
/// Callbacks to receive tap events for polyline placed on this map.
- final VoidCallback onTap;
+ final VoidCallback? onTap;
/// Creates a new [Polyline] object whose values are the same as this instance,
/// unless overwritten by the specified parameters.
Polyline copyWith({
- Color colorParam,
- bool consumeTapEventsParam,
- Cap endCapParam,
- bool geodesicParam,
- JointType jointTypeParam,
- List<PatternItem> patternsParam,
- List<LatLng> pointsParam,
- Cap startCapParam,
- bool visibleParam,
- int widthParam,
- int zIndexParam,
- VoidCallback onTapParam,
+ Color? colorParam,
+ bool? consumeTapEventsParam,
+ Cap? endCapParam,
+ bool? geodesicParam,
+ JointType? jointTypeParam,
+ List<PatternItem>? patternsParam,
+ List<LatLng>? pointsParam,
+ Cap? startCapParam,
+ bool? visibleParam,
+ int? widthParam,
+ int? zIndexParam,
+ VoidCallback? onTapParam,
}) {
return Polyline(
polylineId: polylineId,
@@ -174,10 +158,10 @@
}
/// Converts this object to something serializable in JSON.
- dynamic toJson() {
- final Map<String, dynamic> json = <String, dynamic>{};
+ Object toJson() {
+ final Map<String, Object> json = <String, Object>{};
- void addIfPresent(String fieldName, dynamic value) {
+ void addIfPresent(String fieldName, Object? value) {
if (value != null) {
json[fieldName] = value;
}
@@ -186,10 +170,10 @@
addIfPresent('polylineId', polylineId.value);
addIfPresent('consumeTapEvents', consumeTapEvents);
addIfPresent('color', color.value);
- addIfPresent('endCap', endCap?.toJson());
+ addIfPresent('endCap', endCap.toJson());
addIfPresent('geodesic', geodesic);
- addIfPresent('jointType', jointType?.value);
- addIfPresent('startCap', startCap?.toJson());
+ addIfPresent('jointType', jointType.value);
+ addIfPresent('startCap', startCap.toJson());
addIfPresent('visible', visible);
addIfPresent('width', width);
addIfPresent('zIndex', zIndex);
@@ -209,7 +193,7 @@
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other.runtimeType != runtimeType) return false;
- final Polyline typedOther = other;
+ final Polyline typedOther = other as Polyline;
return polylineId == typedOther.polylineId &&
consumeTapEvents == typedOther.consumeTapEvents &&
color == typedOther.color &&
@@ -227,16 +211,16 @@
@override
int get hashCode => polylineId.hashCode;
- dynamic _pointsToJson() {
- final List<dynamic> result = <dynamic>[];
+ Object _pointsToJson() {
+ final List<Object> result = <Object>[];
for (final LatLng point in points) {
result.add(point.toJson());
}
return result;
}
- dynamic _patternToJson() {
- final List<dynamic> result = <dynamic>[];
+ Object _patternToJson() {
+ final List<Object> result = <Object>[];
for (final PatternItem patternItem in patterns) {
if (patternItem != null) {
result.add(patternItem.toJson());
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline_updates.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline_updates.dart
index f871928..60e0bfe 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline_updates.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline_updates.dart
@@ -2,110 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:ui' show hashValues;
-
-import 'package:flutter/foundation.dart' show setEquals;
-
-import 'utils/polyline.dart';
import 'types.dart';
/// [Polyline] update events to be applied to the [GoogleMap].
///
/// Used in [GoogleMapController] when the map is updated.
// (Do not re-export)
-class PolylineUpdates {
+class PolylineUpdates extends MapsObjectUpdates<Polyline> {
/// Computes [PolylineUpdates] given previous and current [Polyline]s.
- PolylineUpdates.from(Set<Polyline> previous, Set<Polyline> current) {
- if (previous == null) {
- previous = Set<Polyline>.identity();
- }
-
- if (current == null) {
- current = Set<Polyline>.identity();
- }
-
- final Map<PolylineId, Polyline> previousPolylines =
- keyByPolylineId(previous);
- final Map<PolylineId, Polyline> currentPolylines = keyByPolylineId(current);
-
- final Set<PolylineId> prevPolylineIds = previousPolylines.keys.toSet();
- final Set<PolylineId> currentPolylineIds = currentPolylines.keys.toSet();
-
- Polyline idToCurrentPolyline(PolylineId id) {
- return currentPolylines[id];
- }
-
- final Set<PolylineId> _polylineIdsToRemove =
- prevPolylineIds.difference(currentPolylineIds);
-
- final Set<Polyline> _polylinesToAdd = currentPolylineIds
- .difference(prevPolylineIds)
- .map(idToCurrentPolyline)
- .toSet();
-
- /// Returns `true` if [current] is not equals to previous one with the
- /// same id.
- bool hasChanged(Polyline current) {
- final Polyline previous = previousPolylines[current.polylineId];
- return current != previous;
- }
-
- final Set<Polyline> _polylinesToChange = currentPolylineIds
- .intersection(prevPolylineIds)
- .map(idToCurrentPolyline)
- .where(hasChanged)
- .toSet();
-
- polylinesToAdd = _polylinesToAdd;
- polylineIdsToRemove = _polylineIdsToRemove;
- polylinesToChange = _polylinesToChange;
- }
+ PolylineUpdates.from(Set<Polyline> previous, Set<Polyline> current)
+ : super.from(previous, current, objectName: 'polyline');
/// Set of Polylines to be added in this update.
- Set<Polyline> polylinesToAdd;
+ Set<Polyline> get polylinesToAdd => objectsToAdd;
/// Set of PolylineIds to be removed in this update.
- Set<PolylineId> polylineIdsToRemove;
+ Set<PolylineId> get polylineIdsToRemove =>
+ objectIdsToRemove.cast<PolylineId>();
/// Set of Polylines to be changed in this update.
- Set<Polyline> polylinesToChange;
-
- /// Converts this object to something serializable in JSON.
- Map<String, dynamic> toJson() {
- final Map<String, dynamic> updateMap = <String, dynamic>{};
-
- void addIfNonNull(String fieldName, dynamic value) {
- if (value != null) {
- updateMap[fieldName] = value;
- }
- }
-
- addIfNonNull('polylinesToAdd', serializePolylineSet(polylinesToAdd));
- addIfNonNull('polylinesToChange', serializePolylineSet(polylinesToChange));
- addIfNonNull('polylineIdsToRemove',
- polylineIdsToRemove.map<dynamic>((PolylineId m) => m.value).toList());
-
- return updateMap;
- }
-
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- if (other.runtimeType != runtimeType) return false;
- final PolylineUpdates typedOther = other;
- return setEquals(polylinesToAdd, typedOther.polylinesToAdd) &&
- setEquals(polylineIdsToRemove, typedOther.polylineIdsToRemove) &&
- setEquals(polylinesToChange, typedOther.polylinesToChange);
- }
-
- @override
- int get hashCode =>
- hashValues(polylinesToAdd, polylineIdsToRemove, polylinesToChange);
-
- @override
- String toString() {
- return '_PolylineUpdates{polylinesToAdd: $polylinesToAdd, '
- 'polylineIdsToRemove: $polylineIdsToRemove, '
- 'polylinesToChange: $polylinesToChange}';
- }
+ Set<Polyline> get polylinesToChange => objectsToChange;
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/screen_coordinate.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/screen_coordinate.dart
index 965db79..af7a951 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/screen_coordinate.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/screen_coordinate.dart
@@ -4,7 +4,7 @@
import 'dart:ui' show hashValues;
-import 'package:meta/meta.dart' show immutable, required;
+import 'package:meta/meta.dart' show immutable;
/// Represents a point coordinate in the [GoogleMap]'s view.
///
@@ -15,8 +15,8 @@
class ScreenCoordinate {
/// Creates an immutable representation of a point coordinate in the [GoogleMap]'s view.
const ScreenCoordinate({
- @required this.x,
- @required this.y,
+ required this.x,
+ required this.y,
});
/// Represents the number of pixels from the left of the [GoogleMap].
@@ -26,7 +26,7 @@
final int y;
/// Converts this object to something serializable in JSON.
- dynamic toJson() {
+ Object toJson() {
return <String, int>{
"x": x,
"y": y,
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile.dart
index a992b41..bfc3228 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile.dart
@@ -21,13 +21,13 @@
///
/// The image data format must be natively supported for decoding by the platform.
/// e.g on Android it can only be one of the [supported image formats for decoding](https://developer.android.com/guide/topics/media/media-formats#image-formats).
- final Uint8List data;
+ final Uint8List? data;
/// Converts this object to JSON.
- Map<String, dynamic> toJson() {
- final Map<String, dynamic> json = <String, dynamic>{};
+ Object toJson() {
+ final Map<String, Object> json = <String, Object>{};
- void addIfPresent(String fieldName, dynamic value) {
+ void addIfPresent(String fieldName, Object? value) {
if (value != null) {
json[fieldName] = value;
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_overlay.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_overlay.dart
index 3978f23..e31bfb4 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_overlay.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_overlay.dart
@@ -6,30 +6,13 @@
import 'package:flutter/foundation.dart';
import 'types.dart';
-import 'package:meta/meta.dart' show immutable, required;
+import 'package:meta/meta.dart' show immutable;
/// Uniquely identifies a [TileOverlay] among [GoogleMap] tile overlays.
@immutable
-class TileOverlayId {
+class TileOverlayId extends MapsObjectId<TileOverlay> {
/// Creates an immutable identifier for a [TileOverlay].
- TileOverlayId(this.value) : assert(value != null);
-
- /// The value of the [TileOverlayId].
- final String value;
-
- @override
- bool operator ==(Object other) {
- if (other.runtimeType != runtimeType) {
- return false;
- }
- return other is TileOverlayId && other.value == value;
- }
-
- @override
- int get hashCode => value.hashCode;
-
- @override
- String toString() => '${objectRuntimeType(this, 'TileOverlayId')}($value)';
+ TileOverlayId(String value) : super(value);
}
/// A set of images which are displayed on top of the base map tiles.
@@ -61,14 +44,14 @@
/// At zoom level N, the x values of the tile coordinates range from 0 to 2N - 1 and increase from
/// west to east and the y values range from 0 to 2N - 1 and increase from north to south.
///
-class TileOverlay {
+class TileOverlay implements MapsObject {
/// Creates an immutable representation of a [TileOverlay] to draw on [GoogleMap].
const TileOverlay({
- @required this.tileOverlayId,
+ required this.tileOverlayId,
this.fadeIn = true,
this.tileProvider,
this.transparency = 0.0,
- this.zIndex,
+ this.zIndex = 0,
this.visible = true,
this.tileSize = 256,
}) : assert(transparency >= 0.0 && transparency <= 1.0);
@@ -76,11 +59,14 @@
/// Uniquely identifies a [TileOverlay].
final TileOverlayId tileOverlayId;
+ @override
+ TileOverlayId get mapsId => tileOverlayId;
+
/// Whether the tiles should fade in. The default is true.
final bool fadeIn;
/// The tile provider to use for this tile overlay.
- final TileProvider tileProvider;
+ final TileProvider? tileProvider;
/// The transparency of the tile overlay. The default transparency is 0 (opaque).
final double transparency;
@@ -104,12 +90,11 @@
/// Creates a new [TileOverlay] object whose values are the same as this instance,
/// unless overwritten by the specified parameters.
TileOverlay copyWith({
- TileOverlayId tileOverlayId,
- bool fadeInParam,
- double transparencyParam,
- int zIndexParam,
- bool visibleParam,
- int tileSizeParam,
+ bool? fadeInParam,
+ double? transparencyParam,
+ int? zIndexParam,
+ bool? visibleParam,
+ int? tileSizeParam,
}) {
return TileOverlay(
tileOverlayId: tileOverlayId,
@@ -121,11 +106,13 @@
);
}
- /// Converts this object to JSON.
- Map<String, dynamic> toJson() {
- final Map<String, dynamic> json = <String, dynamic>{};
+ TileOverlay clone() => copyWith();
- void addIfPresent(String fieldName, dynamic value) {
+ /// Converts this object to JSON.
+ Object toJson() {
+ final Map<String, Object> json = <String, Object>{};
+
+ void addIfPresent(String fieldName, Object? value) {
if (value != null) {
json[fieldName] = value;
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_overlay_updates.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_overlay_updates.dart
index 2910fc3..1436880 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_overlay_updates.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_overlay_updates.dart
@@ -2,121 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'package:flutter/foundation.dart' show objectRuntimeType, setEquals;
-import 'dart:ui' show hashValues, hashList;
-
-import 'utils/tile_overlay.dart';
import 'types.dart';
/// Update specification for a set of [TileOverlay]s.
-class TileOverlayUpdates {
+class TileOverlayUpdates extends MapsObjectUpdates<TileOverlay> {
/// Computes [TileOverlayUpdates] given previous and current [TileOverlay]s.
- TileOverlayUpdates.from(Set<TileOverlay> previous, Set<TileOverlay> current) {
- if (previous == null) {
- previous = Set<TileOverlay>.identity();
- }
-
- if (current == null) {
- current = Set<TileOverlay>.identity();
- }
-
- final Map<TileOverlayId, TileOverlay> previousTileOverlays =
- keyTileOverlayId(previous);
- final Map<TileOverlayId, TileOverlay> currentTileOverlays =
- keyTileOverlayId(current);
-
- final Set<TileOverlayId> prevTileOverlayIds =
- previousTileOverlays.keys.toSet();
- final Set<TileOverlayId> currentTileOverlayIds =
- currentTileOverlays.keys.toSet();
-
- TileOverlay idToCurrentTileOverlay(TileOverlayId id) {
- return currentTileOverlays[id];
- }
-
- _tileOverlayIdsToRemove =
- prevTileOverlayIds.difference(currentTileOverlayIds);
-
- _tileOverlaysToAdd = currentTileOverlayIds
- .difference(prevTileOverlayIds)
- .map(idToCurrentTileOverlay)
- .toSet();
-
- // Returns `true` if [current] is not equals to previous one with the
- // same id.
- bool hasChanged(TileOverlay current) {
- final TileOverlay previous = previousTileOverlays[current.tileOverlayId];
- return current != previous;
- }
-
- _tileOverlaysToChange = currentTileOverlayIds
- .intersection(prevTileOverlayIds)
- .map(idToCurrentTileOverlay)
- .where(hasChanged)
- .toSet();
- }
+ TileOverlayUpdates.from(Set<TileOverlay> previous, Set<TileOverlay> current)
+ : super.from(previous, current, objectName: 'tileOverlay');
/// Set of TileOverlays to be added in this update.
- Set<TileOverlay> get tileOverlaysToAdd {
- return _tileOverlaysToAdd;
- }
-
- Set<TileOverlay> _tileOverlaysToAdd;
+ Set<TileOverlay> get tileOverlaysToAdd => objectsToAdd;
/// Set of TileOverlayIds to be removed in this update.
- Set<TileOverlayId> get tileOverlayIdsToRemove {
- return _tileOverlayIdsToRemove;
- }
-
- Set<TileOverlayId> _tileOverlayIdsToRemove;
+ Set<TileOverlayId> get tileOverlayIdsToRemove =>
+ objectIdsToRemove.cast<TileOverlayId>();
/// Set of TileOverlays to be changed in this update.
- Set<TileOverlay> get tileOverlaysToChange {
- return _tileOverlaysToChange;
- }
-
- Set<TileOverlay> _tileOverlaysToChange;
-
- /// Converts this object to JSON.
- Map<String, dynamic> toJson() {
- final Map<String, dynamic> updateMap = <String, dynamic>{};
-
- void addIfNonNull(String fieldName, dynamic value) {
- if (value != null) {
- updateMap[fieldName] = value;
- }
- }
-
- addIfNonNull(
- 'tileOverlaysToAdd', serializeTileOverlaySet(_tileOverlaysToAdd));
- addIfNonNull(
- 'tileOverlaysToChange', serializeTileOverlaySet(_tileOverlaysToChange));
- addIfNonNull(
- 'tileOverlayIdsToRemove',
- _tileOverlayIdsToRemove
- .map<dynamic>((TileOverlayId m) => m.value)
- .toList());
-
- return updateMap;
- }
-
- @override
- bool operator ==(Object other) {
- if (other.runtimeType != runtimeType) {
- return false;
- }
- return other is TileOverlayUpdates &&
- setEquals(_tileOverlaysToAdd, other._tileOverlaysToAdd) &&
- setEquals(_tileOverlayIdsToRemove, other._tileOverlayIdsToRemove) &&
- setEquals(_tileOverlaysToChange, other._tileOverlaysToChange);
- }
-
- @override
- int get hashCode => hashValues(hashList(_tileOverlaysToAdd),
- hashList(_tileOverlayIdsToRemove), hashList(_tileOverlaysToChange));
-
- @override
- String toString() {
- return '${objectRuntimeType(this, 'TileOverlayUpdates')}($_tileOverlaysToAdd, $_tileOverlayIdsToRemove, $_tileOverlaysToChange)';
- }
+ Set<TileOverlay> get tileOverlaysToChange => objectsToChange;
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_provider.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_provider.dart
index c3c4f80..abaf38b 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_provider.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_provider.dart
@@ -12,5 +12,5 @@
/// Returns the tile to be used for this tile coordinate.
///
/// See [TileOverlay] for the specification of tile coordinates.
- Future<Tile> getTile(int x, int y, int zoom);
+ Future<Tile> getTile(int x, int y, int? zoom);
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/types.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/types.dart
index 3e2002f..9b7da87 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/types.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/types.dart
@@ -11,6 +11,8 @@
export 'circle.dart';
export 'joint_type.dart';
export 'location.dart';
+export 'maps_object_updates.dart';
+export 'maps_object.dart';
export 'marker_updates.dart';
export 'marker.dart';
export 'pattern_item.dart';
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/ui.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/ui.dart
index 8d84171..1c030e3 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/ui.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/ui.dart
@@ -39,19 +39,19 @@
/// The geographical bounding box for the map camera target.
///
/// A null value means the camera target is unbounded.
- final LatLngBounds bounds;
+ final LatLngBounds? bounds;
/// Unbounded camera target.
static const CameraTargetBounds unbounded = CameraTargetBounds(null);
/// Converts this object to something serializable in JSON.
- dynamic toJson() => <dynamic>[bounds?.toJson()];
+ Object toJson() => <Object?>[bounds?.toJson()];
@override
- bool operator ==(dynamic other) {
+ bool operator ==(Object other) {
if (identical(this, other)) return true;
if (runtimeType != other.runtimeType) return false;
- final CameraTargetBounds typedOther = other;
+ final CameraTargetBounds typedOther = other as CameraTargetBounds;
return bounds == typedOther.bounds;
}
@@ -76,23 +76,23 @@
: assert(minZoom == null || maxZoom == null || minZoom <= maxZoom);
/// The preferred minimum zoom level or null, if unbounded from below.
- final double minZoom;
+ final double? minZoom;
/// The preferred maximum zoom level or null, if unbounded from above.
- final double maxZoom;
+ final double? maxZoom;
/// Unbounded zooming.
static const MinMaxZoomPreference unbounded =
MinMaxZoomPreference(null, null);
/// Converts this object to something serializable in JSON.
- dynamic toJson() => <dynamic>[minZoom, maxZoom];
+ Object toJson() => <Object?>[minZoom, maxZoom];
@override
- bool operator ==(dynamic other) {
+ bool operator ==(Object other) {
if (identical(this, other)) return true;
if (runtimeType != other.runtimeType) return false;
- final MinMaxZoomPreference typedOther = other;
+ final MinMaxZoomPreference typedOther = other as MinMaxZoomPreference;
return minZoom == typedOther.minZoom && maxZoom == typedOther.maxZoom;
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/circle.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/circle.dart
index 5c3af96..18bd31e 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/circle.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/circle.dart
@@ -3,20 +3,14 @@
// found in the LICENSE file.
import '../types.dart';
+import 'maps_object.dart';
/// Converts an [Iterable] of Circles in a Map of CircleId -> Circle.
Map<CircleId, Circle> keyByCircleId(Iterable<Circle> circles) {
- if (circles == null) {
- return <CircleId, Circle>{};
- }
- return Map<CircleId, Circle>.fromEntries(circles.map((Circle circle) =>
- MapEntry<CircleId, Circle>(circle.circleId, circle.clone())));
+ return keyByMapsObjectId<Circle>(circles).cast<CircleId, Circle>();
}
/// Converts a Set of Circles into something serializable in JSON.
-List<Map<String, dynamic>> serializeCircleSet(Set<Circle> circles) {
- if (circles == null) {
- return null;
- }
- return circles.map<Map<String, dynamic>>((Circle p) => p.toJson()).toList();
+Object serializeCircleSet(Set<Circle> circles) {
+ return serializeMapsObjectSet(circles);
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/maps_object.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/maps_object.dart
new file mode 100644
index 0000000..fa5a7e7
--- /dev/null
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/maps_object.dart
@@ -0,0 +1,18 @@
+// Copyright 2019 The Chromium 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 '../maps_object.dart';
+
+/// Converts an [Iterable] of [MapsObject]s in a Map of [MapObjectId] -> [MapObject].
+Map<MapsObjectId<T>, T> keyByMapsObjectId<T extends MapsObject>(
+ Iterable<T> objects) {
+ return Map<MapsObjectId<T>, T>.fromEntries(objects.map((T object) =>
+ MapEntry<MapsObjectId<T>, T>(
+ object.mapsId as MapsObjectId<T>, object.clone())));
+}
+
+/// Converts a Set of [MapsObject]s into something serializable in JSON.
+Object serializeMapsObjectSet(Set<MapsObject> mapsObjects) {
+ return mapsObjects.map<Object>((MapsObject p) => p.toJson()).toList();
+}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/marker.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/marker.dart
index 7a2c76d..057bebd 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/marker.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/marker.dart
@@ -3,20 +3,14 @@
// found in the LICENSE file.
import '../types.dart';
+import 'maps_object.dart';
/// Converts an [Iterable] of Markers in a Map of MarkerId -> Marker.
Map<MarkerId, Marker> keyByMarkerId(Iterable<Marker> markers) {
- if (markers == null) {
- return <MarkerId, Marker>{};
- }
- return Map<MarkerId, Marker>.fromEntries(markers.map((Marker marker) =>
- MapEntry<MarkerId, Marker>(marker.markerId, marker.clone())));
+ return keyByMapsObjectId<Marker>(markers).cast<MarkerId, Marker>();
}
/// Converts a Set of Markers into something serializable in JSON.
-List<Map<String, dynamic>> serializeMarkerSet(Set<Marker> markers) {
- if (markers == null) {
- return null;
- }
- return markers.map<Map<String, dynamic>>((Marker m) => m.toJson()).toList();
+Object serializeMarkerSet(Set<Marker> markers) {
+ return serializeMapsObjectSet(markers);
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polygon.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polygon.dart
index 9434dda..050ecaf 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polygon.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polygon.dart
@@ -3,20 +3,14 @@
// found in the LICENSE file.
import '../types.dart';
+import 'maps_object.dart';
/// Converts an [Iterable] of Polygons in a Map of PolygonId -> Polygon.
Map<PolygonId, Polygon> keyByPolygonId(Iterable<Polygon> polygons) {
- if (polygons == null) {
- return <PolygonId, Polygon>{};
- }
- return Map<PolygonId, Polygon>.fromEntries(polygons.map((Polygon polygon) =>
- MapEntry<PolygonId, Polygon>(polygon.polygonId, polygon.clone())));
+ return keyByMapsObjectId<Polygon>(polygons).cast<PolygonId, Polygon>();
}
/// Converts a Set of Polygons into something serializable in JSON.
-List<Map<String, dynamic>> serializePolygonSet(Set<Polygon> polygons) {
- if (polygons == null) {
- return null;
- }
- return polygons.map<Map<String, dynamic>>((Polygon p) => p.toJson()).toList();
+Object serializePolygonSet(Set<Polygon> polygons) {
+ return serializeMapsObjectSet(polygons);
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polyline.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polyline.dart
index 9cef631..8f4098f 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polyline.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polyline.dart
@@ -3,23 +3,14 @@
// found in the LICENSE file.
import '../types.dart';
+import 'maps_object.dart';
/// Converts an [Iterable] of Polylines in a Map of PolylineId -> Polyline.
Map<PolylineId, Polyline> keyByPolylineId(Iterable<Polyline> polylines) {
- if (polylines == null) {
- return <PolylineId, Polyline>{};
- }
- return Map<PolylineId, Polyline>.fromEntries(polylines.map(
- (Polyline polyline) => MapEntry<PolylineId, Polyline>(
- polyline.polylineId, polyline.clone())));
+ return keyByMapsObjectId<Polyline>(polylines).cast<PolylineId, Polyline>();
}
/// Converts a Set of Polylines into something serializable in JSON.
-List<Map<String, dynamic>> serializePolylineSet(Set<Polyline> polylines) {
- if (polylines == null) {
- return null;
- }
- return polylines
- .map<Map<String, dynamic>>((Polyline p) => p.toJson())
- .toList();
+Object serializePolylineSet(Set<Polyline> polylines) {
+ return serializeMapsObjectSet(polylines);
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/tile_overlay.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/tile_overlay.dart
index 0736c83..336f814 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/tile_overlay.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/tile_overlay.dart
@@ -1,23 +1,18 @@
+// Copyright 2019 The Chromium 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 '../types.dart';
+import 'maps_object.dart';
/// Converts an [Iterable] of TileOverlay in a Map of TileOverlayId -> TileOverlay.
Map<TileOverlayId, TileOverlay> keyTileOverlayId(
Iterable<TileOverlay> tileOverlays) {
- if (tileOverlays == null) {
- return <TileOverlayId, TileOverlay>{};
- }
- return Map<TileOverlayId, TileOverlay>.fromEntries(tileOverlays.map(
- (TileOverlay tileOverlay) => MapEntry<TileOverlayId, TileOverlay>(
- tileOverlay.tileOverlayId, tileOverlay)));
+ return keyByMapsObjectId<TileOverlay>(tileOverlays)
+ .cast<TileOverlayId, TileOverlay>();
}
/// Converts a Set of TileOverlays into something serializable in JSON.
-List<Map<String, dynamic>> serializeTileOverlaySet(
- Set<TileOverlay> tileOverlays) {
- if (tileOverlays == null) {
- return null;
- }
- return tileOverlays
- .map<Map<String, dynamic>>((TileOverlay p) => p.toJson())
- .toList();
+Object serializeTileOverlaySet(Set<TileOverlay> tileOverlays) {
+ return serializeMapsObjectSet(tileOverlays);
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml
index 487a54b..8b31fee 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml
@@ -3,22 +3,22 @@
homepage: https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter_platform_interface
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
-version: 1.2.0
+version: 2.0.0-nullsafety
dependencies:
flutter:
sdk: flutter
meta: ^1.0.5
- plugin_platform_interface: ^1.0.1
- stream_transform: ^1.2.0
+ plugin_platform_interface: ^1.1.0-nullsafety.2
+ stream_transform: ^2.0.0-nullsafety.0
collection: ^1.14.13
dev_dependencies:
flutter_test:
sdk: flutter
- mockito: ^4.1.1
+ mockito: ^5.0.0-nullsafety.0
pedantic: ^1.8.0
environment:
- sdk: ">=2.3.0 <3.0.0"
+ sdk: '>=2.12.0-0 <3.0.0'
flutter: ">=1.9.1+hotfix.4"
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/maps_object_test.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/maps_object_test.dart
new file mode 100644
index 0000000..65692bd
--- /dev/null
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/maps_object_test.dart
@@ -0,0 +1,45 @@
+// Copyright 2017 The Chromium 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_test/flutter_test.dart';
+import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
+import 'package:google_maps_flutter_platform_interface/src/types/utils/maps_object.dart';
+
+import 'test_maps_object.dart';
+
+void main() {
+ TestWidgetsFlutterBinding.ensureInitialized();
+
+ test('keyByMapsObjectId', () async {
+ final MapsObjectId<TestMapsObject> id1 = MapsObjectId<TestMapsObject>('1');
+ final MapsObjectId<TestMapsObject> id2 = MapsObjectId<TestMapsObject>('2');
+ final MapsObjectId<TestMapsObject> id3 = MapsObjectId<TestMapsObject>('3');
+ final TestMapsObject object1 = TestMapsObject(id1);
+ final TestMapsObject object2 = TestMapsObject(id2, data: 2);
+ final TestMapsObject object3 = TestMapsObject(id3);
+ expect(
+ keyByMapsObjectId(<TestMapsObject>{object1, object2, object3}),
+ <MapsObjectId<TestMapsObject>, TestMapsObject>{
+ id1: object1,
+ id2: object2,
+ id3: object3,
+ });
+ });
+
+ test('serializeMapsObjectSet', () async {
+ final MapsObjectId<TestMapsObject> id1 = MapsObjectId<TestMapsObject>('1');
+ final MapsObjectId<TestMapsObject> id2 = MapsObjectId<TestMapsObject>('2');
+ final MapsObjectId<TestMapsObject> id3 = MapsObjectId<TestMapsObject>('3');
+ final TestMapsObject object1 = TestMapsObject(id1);
+ final TestMapsObject object2 = TestMapsObject(id2, data: 2);
+ final TestMapsObject object3 = TestMapsObject(id3);
+ expect(
+ serializeMapsObjectSet(<TestMapsObject>{object1, object2, object3}),
+ <Map<String, Object>>[
+ {'id': '1'},
+ {'id': '2'},
+ {'id': '3'}
+ ]);
+ });
+}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/maps_object_updates_test.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/maps_object_updates_test.dart
new file mode 100644
index 0000000..68f4c58
--- /dev/null
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/maps_object_updates_test.dart
@@ -0,0 +1,160 @@
+// Copyright 2017 The Chromium 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:ui' show hashValues, hashList;
+
+import 'package:flutter/rendering.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:google_maps_flutter_platform_interface/src/types/utils/maps_object.dart';
+import 'package:google_maps_flutter_platform_interface/src/types/maps_object_updates.dart';
+import 'package:google_maps_flutter_platform_interface/src/types/maps_object.dart';
+
+import 'test_maps_object.dart';
+
+class TestMapsObjectUpdate extends MapsObjectUpdates<TestMapsObject> {
+ TestMapsObjectUpdate.from(
+ Set<TestMapsObject> previous, Set<TestMapsObject> current)
+ : super.from(previous, current, objectName: 'testObject');
+}
+
+void main() {
+ TestWidgetsFlutterBinding.ensureInitialized();
+
+ group('tile overlay updates tests', () {
+ test('Correctly set toRemove, toAdd and toChange', () async {
+ final TestMapsObject to1 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id1'));
+ final TestMapsObject to2 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id2'));
+ final TestMapsObject to3 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id3'));
+ final TestMapsObject to3Changed =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id3'), data: 2);
+ final TestMapsObject to4 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id4'));
+ final Set<TestMapsObject> previous =
+ Set.from(<TestMapsObject>[to1, to2, to3]);
+ final Set<TestMapsObject> current =
+ Set.from(<TestMapsObject>[to2, to3Changed, to4]);
+ final TestMapsObjectUpdate updates =
+ TestMapsObjectUpdate.from(previous, current);
+
+ final Set<MapsObjectId<TestMapsObject>> toRemove = Set.from(
+ <MapsObjectId<TestMapsObject>>[MapsObjectId<TestMapsObject>('id1')]);
+ expect(updates.objectIdsToRemove, toRemove);
+
+ final Set<TestMapsObject> toAdd = Set.from(<TestMapsObject>[to4]);
+ expect(updates.objectsToAdd, toAdd);
+
+ final Set<TestMapsObject> toChange =
+ Set.from(<TestMapsObject>[to3Changed]);
+ expect(updates.objectsToChange, toChange);
+ });
+
+ test('toJson', () async {
+ final TestMapsObject to1 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id1'));
+ final TestMapsObject to2 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id2'));
+ final TestMapsObject to3 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id3'));
+ final TestMapsObject to3Changed =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id3'), data: 2);
+ final TestMapsObject to4 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id4'));
+ final Set<TestMapsObject> previous =
+ Set.from(<TestMapsObject>[to1, to2, to3]);
+ final Set<TestMapsObject> current =
+ Set.from(<TestMapsObject>[to2, to3Changed, to4]);
+ final TestMapsObjectUpdate updates =
+ TestMapsObjectUpdate.from(previous, current);
+
+ final Object json = updates.toJson();
+ expect(json, <String, Object>{
+ 'testObjectsToAdd': serializeMapsObjectSet(updates.objectsToAdd),
+ 'testObjectsToChange': serializeMapsObjectSet(updates.objectsToChange),
+ 'testObjectIdsToRemove': updates.objectIdsToRemove
+ .map<String>((MapsObjectId<TestMapsObject> m) => m.value)
+ .toList()
+ });
+ });
+
+ test('equality', () async {
+ final TestMapsObject to1 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id1'));
+ final TestMapsObject to2 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id2'));
+ final TestMapsObject to3 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id3'));
+ final TestMapsObject to3Changed =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id3'), data: 2);
+ final TestMapsObject to4 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id4'));
+ final Set<TestMapsObject> previous =
+ Set.from(<TestMapsObject>[to1, to2, to3]);
+ final Set<TestMapsObject> current1 =
+ Set.from(<TestMapsObject>[to2, to3Changed, to4]);
+ final Set<TestMapsObject> current2 =
+ Set.from(<TestMapsObject>[to2, to3Changed, to4]);
+ final Set<TestMapsObject> current3 = Set.from(<TestMapsObject>[to2, to4]);
+ final TestMapsObjectUpdate updates1 =
+ TestMapsObjectUpdate.from(previous, current1);
+ final TestMapsObjectUpdate updates2 =
+ TestMapsObjectUpdate.from(previous, current2);
+ final TestMapsObjectUpdate updates3 =
+ TestMapsObjectUpdate.from(previous, current3);
+ expect(updates1, updates2);
+ expect(updates1, isNot(updates3));
+ });
+
+ test('hashCode', () async {
+ final TestMapsObject to1 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id1'));
+ final TestMapsObject to2 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id2'));
+ final TestMapsObject to3 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id3'));
+ final TestMapsObject to3Changed =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id3'), data: 2);
+ final TestMapsObject to4 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id4'));
+ final Set<TestMapsObject> previous =
+ Set.from(<TestMapsObject>[to1, to2, to3]);
+ final Set<TestMapsObject> current =
+ Set.from(<TestMapsObject>[to2, to3Changed, to4]);
+ final TestMapsObjectUpdate updates =
+ TestMapsObjectUpdate.from(previous, current);
+ expect(
+ updates.hashCode,
+ hashValues(
+ hashList(updates.objectsToAdd),
+ hashList(updates.objectIdsToRemove),
+ hashList(updates.objectsToChange)));
+ });
+
+ test('toString', () async {
+ final TestMapsObject to1 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id1'));
+ final TestMapsObject to2 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id2'));
+ final TestMapsObject to3 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id3'));
+ final TestMapsObject to3Changed =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id3'), data: 2);
+ final TestMapsObject to4 =
+ TestMapsObject(MapsObjectId<TestMapsObject>('id4'));
+ final Set<TestMapsObject> previous =
+ Set.from(<TestMapsObject>[to1, to2, to3]);
+ final Set<TestMapsObject> current =
+ Set.from(<TestMapsObject>[to2, to3Changed, to4]);
+ final TestMapsObjectUpdate updates =
+ TestMapsObjectUpdate.from(previous, current);
+ expect(
+ updates.toString(),
+ 'TestMapsObjectUpdate(add: ${updates.objectsToAdd}, '
+ 'remove: ${updates.objectIdsToRemove}, '
+ 'change: ${updates.objectsToChange})');
+ });
+ });
+}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/test_maps_object.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/test_maps_object.dart
new file mode 100644
index 0000000..e15c73f
--- /dev/null
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/test_maps_object.dart
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium 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:ui' show hashValues;
+import 'package:flutter/rendering.dart';
+import 'package:google_maps_flutter_platform_interface/src/types/maps_object_updates.dart';
+import 'package:google_maps_flutter_platform_interface/src/types/maps_object.dart';
+
+/// A trivial TestMapsObject implementation for testing updates with.
+class TestMapsObject implements MapsObject {
+ TestMapsObject(this.mapsId, {this.data = 1});
+
+ final MapsObjectId<TestMapsObject> mapsId;
+
+ final int data;
+
+ @override
+ TestMapsObject clone() {
+ return TestMapsObject(mapsId, data: data);
+ }
+
+ @override
+ Object toJson() {
+ return <String, Object>{'id': mapsId.value};
+ }
+
+ @override
+ bool operator ==(Object other) {
+ if (other.runtimeType != runtimeType) {
+ return false;
+ }
+ return other is TestMapsObject &&
+ mapsId == other.mapsId &&
+ data == other.data;
+ }
+
+ @override
+ int get hashCode => hashValues(mapsId, data);
+}
+
+class TestMapsObjectUpdate extends MapsObjectUpdates<TestMapsObject> {
+ TestMapsObjectUpdate.from(
+ Set<TestMapsObject> previous, Set<TestMapsObject> current)
+ : super.from(previous, current, objectName: 'testObject');
+}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_overlay_test.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_overlay_test.dart
index bb0621d..87380fd 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_overlay_test.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_overlay_test.dart
@@ -34,13 +34,15 @@
zIndex: 1,
visible: false,
tileSize: 128);
- final Map<String, dynamic> json = tileOverlay.toJson();
- expect(json['tileOverlayId'], 'id');
- expect(json['fadeIn'], false);
- expect(json['transparency'], moreOrLessEquals(0.1));
- expect(json['zIndex'], 1);
- expect(json['visible'], false);
- expect(json['tileSize'], 128);
+ final Object json = tileOverlay.toJson();
+ expect(json, <String, Object>{
+ 'tileOverlayId': 'id',
+ 'fadeIn': false,
+ 'transparency': moreOrLessEquals(0.1),
+ 'zIndex': 1,
+ 'visible': false,
+ 'tileSize': 128,
+ });
});
test('invalid transparency throws', () async {
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_overlay_updates_test.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_overlay_updates_test.dart
index 980a203..f622ca5 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_overlay_updates_test.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_overlay_updates_test.dart
@@ -49,13 +49,13 @@
final TileOverlayUpdates updates =
TileOverlayUpdates.from(previous, current);
- final Map<String, dynamic> json = updates.toJson();
- expect(json, <String, dynamic>{
+ final Object json = updates.toJson();
+ expect(json, <String, Object>{
'tileOverlaysToAdd': serializeTileOverlaySet(updates.tileOverlaysToAdd),
'tileOverlaysToChange':
serializeTileOverlaySet(updates.tileOverlaysToChange),
'tileOverlayIdsToRemove': updates.tileOverlayIdsToRemove
- .map<dynamic>((TileOverlayId m) => m.value)
+ .map<String>((TileOverlayId m) => m.value)
.toList()
});
});
@@ -117,9 +117,9 @@
TileOverlayUpdates.from(previous, current);
expect(
updates.toString(),
- 'TileOverlayUpdates(${updates.tileOverlaysToAdd}, '
- '${updates.tileOverlayIdsToRemove}, '
- '${updates.tileOverlaysToChange})');
+ 'TileOverlayUpdates(add: ${updates.tileOverlaysToAdd}, '
+ 'remove: ${updates.tileOverlayIdsToRemove}, '
+ 'change: ${updates.tileOverlaysToChange})');
});
});
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_test.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_test.dart
index 0be9a7c..3e0fe99 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_test.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_test.dart
@@ -13,16 +13,21 @@
test('toJson returns correct format', () async {
final Uint8List data = Uint8List.fromList([0, 1]);
final Tile tile = Tile(100, 200, data);
- final Map<String, dynamic> json = tile.toJson();
- expect(json['width'], 100);
- expect(json['height'], 200);
- expect(json['data'], data);
+ final Object json = tile.toJson();
+ expect(json, <String, Object>{
+ 'width': 100,
+ 'height': 200,
+ 'data': data,
+ });
});
- test('toJson returns empty if nothing presents', () async {
- final Tile tile = Tile(null, null, null);
- final Map<String, dynamic> json = tile.toJson();
- expect(json.isEmpty, true);
+ test('toJson handles null data', () async {
+ final Tile tile = Tile(0, 0, null);
+ final Object json = tile.toJson();
+ expect(json, <String, Object>{
+ 'width': 0,
+ 'height': 0,
+ });
});
});
}
diff --git a/script/nnbd_plugins.sh b/script/nnbd_plugins.sh
index 5a54a7f..3e82ac2 100644
--- a/script/nnbd_plugins.sh
+++ b/script/nnbd_plugins.sh
@@ -15,6 +15,7 @@
"file_selector"
"flutter_plugin_android_lifecycle"
"flutter_webview"
+ "google_maps_flutter"
"google_sign_in"
"image_picker"
"ios_platform_images"
@@ -38,7 +39,7 @@
readonly NON_NNBD_PLUGINS_LIST=(
"camera"
- # "google_maps_flutter"
+ "google_maps_flutter" # half migrated
# "image_picker"
# "in_app_purchase"
# "quick_actions"