From 5a6e3b1f769587df0ec620facf709b6a11698b38 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 13 Jan 2021 14:00:57 -0800 Subject: [PATCH 1/7] tile overlay format doc updates compelete tests --- .../CHANGELOG.md | 4 + .../method_channel_google_maps_flutter.dart | 57 +++++++ .../google_maps_flutter_platform.dart | 35 ++++ .../lib/src/types/tile.dart | 39 +++++ .../lib/src/types/tile_overlay.dart | 159 ++++++++++++++++++ .../lib/src/types/tile_overlay_updates.dart | 125 ++++++++++++++ .../lib/src/types/tile_provider.dart | 14 ++ .../lib/src/types/types.dart | 5 + .../lib/src/types/utils/tile_overlay.dart | 23 +++ .../google_maps_flutter_platform_test.dart | 3 - .../test/types/tile_overlay_test.dart | 124 ++++++++++++++ .../test/types/tile_overlay_updates_test.dart | 121 +++++++++++++ .../test/types/tile_test.dart | 28 +++ 13 files changed, 734 insertions(+), 3 deletions(-) create mode 100644 packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile.dart create mode 100644 packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_overlay.dart create mode 100644 packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_overlay_updates.dart create mode 100644 packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_provider.dart create mode 100644 packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/tile_overlay.dart create mode 100644 packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_overlay_test.dart create mode 100644 packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_overlay_updates_test.dart create mode 100644 packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_test.dart 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 1e761681e543..4273f596cf39 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,7 @@ +## 1.2.0 + +* Add TileOverlay support. + ## 1.1.0 * Add support for holes in Polygons. 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 31392354d946..c22278e59776 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 @@ -33,6 +33,10 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform { return _channels[mapId]; } + // Keep a collection of id -> GetTileCallback + // Every method call passes the int mapId + final Map _getTileCallbacks = {}; + /// Initializes the platform interface with [id]. /// /// This method is called when the plugin is first initialized. @@ -184,6 +188,15 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform { LatLng.fromJson(call.arguments['position']), )); break; + case 'tileOverlay#getTile': + final getTileCallback = _getTileCallbacks[mapId]; + final Tile tile = await getTileCallback( + call.arguments['tileOverlayId'], + call.arguments['x'], + call.arguments['y'], + call.arguments['zoom'], + ); + return tile.toJson(); default: throw MissingPluginException(); } @@ -281,6 +294,40 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform { ); } + /// 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. + @override + Future updateTileOverlays( + TileOverlayUpdates tileOverlayUpdates, { + @required int mapId, + }) { + assert(tileOverlayUpdates != null); + return channel(mapId).invokeMethod( + 'tileOverlays#update', + tileOverlayUpdates.toJson(), + ); + } + + /// 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 API 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 clearTileCache( + TileOverlayId tileOverlayId, { + @required int mapId, + }) { + return channel(mapId) + .invokeMethod('tileOverlays#clearTileCache', { + 'tileOverlayId': tileOverlayId.value, + }); + } + /// Starts an animated change of the map camera position. /// /// The returned [Future] completes after the change has been started on the @@ -451,6 +498,16 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform { return channel(mapId).invokeMethod('map#takeSnapshot'); } + /// Sets the `MapGetTileCallback` with mapId. + /// + /// `mapId` and `callback` must not be null. + @override + void setGetTileCallback( + {@required int mapId, @required MapGetTileCallback callback}) { + assert(mapId != null && callback != null); + _getTileCallbacks[mapId] = callback; + } + /// 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 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 a4f487740811..a1a6c87f3289 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 @@ -15,6 +15,10 @@ import 'package:google_maps_flutter_platform_interface/src/method_channel/method import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; +/// Callback method for when a [Tile] is requested from a [TileProvider]. +typedef Future MapGetTileCallback( + TileOverlayId tileOverlayId, int x, int y, int zoom); + /// The interface that platform-specific implementations of `google_maps_flutter` must extend. /// /// Avoid `implements` of this interface. Using `implements` makes adding any new @@ -115,6 +119,31 @@ abstract class GoogleMapsFlutterPlatform extends PlatformInterface { throw UnimplementedError('updateCircles() has not been implemented.'); } + /// 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. + Future updateTileOverlays( + TileOverlayUpdates tileOverlayUpdates, { + @required int mapId, + }) { + throw UnimplementedError('updateTileOverlays() has not been implemented.'); + } + + /// 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 API maintains a small + /// in-memory cache of tiles. If you want to cache tiles for longer, you + /// should implement an on-disk cache. + Future clearTileCache( + TileOverlayId tileOverlayId, { + @required int mapId, + }) { + throw UnimplementedError('clearTileCache() has not been implemented.'); + } + /// Starts an animated change of the map camera position. /// /// The returned [Future] completes after the change has been started on the @@ -246,6 +275,12 @@ abstract class GoogleMapsFlutterPlatform extends PlatformInterface { throw UnimplementedError('takeSnapshot() has not been implemented.'); } + /// Set the [MapGetTileCallback] for the map, which will be called + /// when a [Tile] is requested for an added [TileProvider]. + void setGetTileCallback({@required int mapId, MapGetTileCallback callback}) { + throw UnimplementedError('onGetTile() has not been implemented.'); + } + // The following are the 11 possible streams of data from the native side // into the plugin 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 new file mode 100644 index 000000000000..38c9e69de38e --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile.dart @@ -0,0 +1,39 @@ +// 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:typed_data'; +import 'package:meta/meta.dart' show immutable; + +/// Contains information about a Tile that is returned by a [TileProvider]. +@immutable +class Tile { + /// Creates an immutable representation of a [Tile] to draw by [TileProvider]. + const Tile(this.width, this.height, this.data); + + /// The width of the image encoded by data in pixels. + final int width; + + /// The height of the image encoded by data in pixels. + final int height; + + /// A byte array containing the image data. + final Uint8List data; + + /// Converts this object to JSON. + dynamic toJson() { + final Map json = {}; + + void addIfPresent(String fieldName, dynamic value) { + if (value != null) { + json[fieldName] = value; + } + } + + addIfPresent('width', width); + addIfPresent('height', height); + addIfPresent('data', data); + + return json; + } +} 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 new file mode 100644 index 000000000000..824bd80b6208 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_overlay.dart @@ -0,0 +1,159 @@ +// 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 'types.dart'; +import 'package:meta/meta.dart' show immutable, required; + +/// Uniquely identifies a [TileOverlay] among [GoogleMap] tile overlays. +/// +/// This does not have to be globally unique, only unique among the list. +@immutable +class TileOverlayId { + /// Creates an immutable identifier for a [TileOverlay]. + TileOverlayId(this.value) : assert(value != null); + + /// value of the [TileOverlayId]. + final String value; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + if (other.runtimeType != runtimeType) return false; + final TileOverlayId typedOther = other; + return value == typedOther.value; + } + + @override + int get hashCode => value.hashCode; + + @override + String toString() { + return 'TileOverlay{value: $value}'; + } +} + +/// A Tile Overlay is a set of images which are displayed on top of the base map tiles. +/// These tiles may be transparent, allowing you to add features to existing maps. +/// +/// Tile Coordinates +/// +/// Note that the world is projected using the Mercator projection +/// (see [Wikipedia](https://en.wikipedia.org/wiki/Mercator_projection)) with the left (west) side +/// of the map corresponding to -180 degrees of longitude and the right (east) side of the map +/// corresponding to 180 degrees of longitude. To make the map square, the top (north) side of the +/// map corresponds to 85.0511 degrees of latitude and the bottom (south) side of the map +/// corresponds to -85.0511 degrees of latitude. Areas outside this latitude range are not rendered. +/// +/// At each zoom level, the map is divided into tiles and only the tiles that overlap the screen are +/// downloaded and rendered. Each tile is square and the map is divided into tiles as follows: +/// +/// * At zoom level 0, one tile represents the entire world. The coordinates of that tile are +/// (x, y) = (0, 0). +/// * At zoom level 1, the world is divided into 4 tiles arranged in a 2 x 2 grid. +/// * ... +/// * At zoom level N, the world is divided into 4N tiles arranged in a 2N x 2N grid. +/// +/// Note that the minimum zoom level that the camera supports (which can depend on various factors) +/// is GoogleMap.getMinZoomLevel and the maximum zoom level is GoogleMap.getMaxZoomLevel. +/// +/// The coordinates of the tiles are measured from the top left (northwest) corner of the map. +/// 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 { + /// Creates an immutable representation of a [TileOverlay] to draw on [GoogleMap]. + const TileOverlay({ + @required this.tileOverlayId, + this.fadeIn = true, + this.tileProvider, + this.transparency = 0.0, + this.zIndex, + this.visible = true, + this.tileSize = 256, + }) : assert(transparency >= 0.0 && transparency <= 1.0); + + /// Uniquely identifies a [TileOverlay]. + final TileOverlayId 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; + + /// The transparency of the tile overlay. The default transparency is 0 (opaque). + final double transparency; + + /// The tile overlay's zIndex, i.e., the order in which it will be drawn where + /// overlays with larger values are drawn above those with lower values + final int zIndex; + + /// The visibility for the tile overlay. The default visibility is true. + final bool visible; + + /// Specifies the number of pixels (not points) that the returned tile images will prefer + /// to display as. iOS only. + /// + /// Defaults to 256, which is the traditional size of Google Maps tiles. + /// As an example, an application developer may wish to provide retina tiles (512 pixel edge length) + /// on retina devices, to keep the same number of tiles per view as the default value of 256 + /// would give on a non-retina device. + final int tileSize; + + /// Creates a new [Polygon] 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, + }) { + return TileOverlay( + tileOverlayId: tileOverlayId, + fadeIn: fadeInParam ?? fadeIn, + transparency: transparencyParam ?? transparency, + zIndex: zIndexParam ?? zIndex, + visible: visibleParam ?? visible, + tileSize: tileSizeParam ?? tileSize, + ); + } + + /// Converts this object to JSON. + dynamic toJson() { + final Map json = {}; + + void addIfPresent(String fieldName, dynamic value) { + if (value != null) { + json[fieldName] = value; + } + } + + addIfPresent('tileOverlayId', tileOverlayId.value); + addIfPresent('fadeIn', fadeIn); + addIfPresent('transparency', transparency); + addIfPresent('zIndex', zIndex); + addIfPresent('visible', visible); + addIfPresent('tileSize', tileSize); + + return json; + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + if (other.runtimeType != runtimeType) return false; + final TileOverlay typedOther = other; + return tileOverlayId == typedOther.tileOverlayId && + fadeIn == typedOther.fadeIn && + transparency == typedOther.transparency && + zIndex == typedOther.zIndex && + visible == typedOther.visible && + tileSize == typedOther.tileSize; + } + + @override + int get hashCode => tileOverlayId.hashCode; +} 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 new file mode 100644 index 000000000000..9b6e096cd981 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_overlay_updates.dart @@ -0,0 +1,125 @@ +// 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 'package:flutter/foundation.dart' show setEquals; + +import 'utils/tile_overlay.dart'; +import 'types.dart'; + +/// Represents the details of an update events of [TileOverlay]s. +class TileOverlayUpdates { + /// Computes [TileOverlayUpdates] given previous and current [TileOverlay]s. + TileOverlayUpdates.from(Set previous, Set current) { + if (previous == null) { + previous = Set.identity(); + } + + if (current == null) { + current = Set.identity(); + } + + final Map previousTileOverlays = + keyTileOverlayId(previous); + final Map currentTileOverlays = + keyTileOverlayId(current); + + final Set prevTileOverlayIds = + previousTileOverlays.keys.toSet(); + final Set 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(); + } + + /// Set of TileOverlays to be added in this update. + Set get tileOverlaysToAdd { + return _tileOverlaysToAdd; + } + + Set _tileOverlaysToAdd; + + /// Set of TileOverlayIds to be removed in this update. + Set get tileOverlayIdsToRemove { + return _tileOverlayIdsToRemove; + } + + Set _tileOverlayIdsToRemove; + + /// Set of TileOverlays to be changed in this update. + Set get tileOverlaysToChange { + return _tileOverlaysToChange; + } + + Set _tileOverlaysToChange; + + /// Converts this object to JSON. + Map toJson() { + final Map updateMap = {}; + + void addIfNonNull(String fieldName, dynamic value) { + if (value != null) { + updateMap[fieldName] = value; + } + } + + addIfNonNull( + 'tileOverlaysToAdd', serializeTileOverlaySet(_tileOverlaysToAdd)); + addIfNonNull( + 'tileOverlaysToChange', serializeTileOverlaySet(_tileOverlaysToChange)); + addIfNonNull( + 'tileOverlayIdsToRemove', + _tileOverlayIdsToRemove + .map((TileOverlayId m) => m.value) + .toList()); + + return updateMap; + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + if (other.runtimeType != runtimeType) return false; + final TileOverlayUpdates typedOther = other; + return setEquals(_tileOverlaysToAdd, typedOther._tileOverlaysToAdd) && + setEquals( + _tileOverlayIdsToRemove, typedOther._tileOverlayIdsToRemove) && + setEquals(_tileOverlaysToChange, typedOther._tileOverlaysToChange); + } + + @override + int get hashCode => + _tileOverlaysToAdd.hashCode ^ + _tileOverlayIdsToRemove.hashCode ^ + _tileOverlaysToChange.hashCode; + + @override + String toString() { + return 'TileOverlayUpdates{tileOverlaysToAdd: $_tileOverlaysToAdd, ' + 'tileOverlayIdsToRemove: $_tileOverlayIdsToRemove, ' + 'tileOverlaysToChange: $_tileOverlaysToChange}'; + } +} 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 new file mode 100644 index 000000000000..f0754159c941 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/tile_provider.dart @@ -0,0 +1,14 @@ +// 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 'types.dart'; + +/// An interface for a class that provides the tile images for a TileOverlay. +abstract class TileProvider { + /// Stub tile that is used to indicate that no tile exists for a specific tile coordinate. + static const Tile noTile = Tile(-1, -1, null); + + /// Returns the tile to be used for this tile coordinate. + Future 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 e56c3a5dd646..b872f2ff84ed 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 @@ -19,6 +19,10 @@ export 'polygon.dart'; export 'polyline_updates.dart'; export 'polyline.dart'; export 'screen_coordinate.dart'; +export 'tile.dart'; +export 'tile_overlay.dart'; +export 'tile_overlay_updates.dart'; +export 'tile_provider.dart'; export 'ui.dart'; // Export the utils, they're used by the Widget @@ -26,3 +30,4 @@ export 'utils/circle.dart'; export 'utils/marker.dart'; export 'utils/polygon.dart'; export 'utils/polyline.dart'; +export 'utils/tile_overlay.dart'; 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 new file mode 100644 index 000000000000..0736c836481f --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/tile_overlay.dart @@ -0,0 +1,23 @@ +import '../types.dart'; + +/// Converts an [Iterable] of TileOverlay in a Map of TileOverlayId -> TileOverlay. +Map keyTileOverlayId( + Iterable tileOverlays) { + if (tileOverlays == null) { + return {}; + } + return Map.fromEntries(tileOverlays.map( + (TileOverlay tileOverlay) => MapEntry( + tileOverlay.tileOverlayId, tileOverlay))); +} + +/// Converts a Set of TileOverlays into something serializable in JSON. +List> serializeTileOverlaySet( + Set tileOverlays) { + if (tileOverlays == null) { + return null; + } + return tileOverlays + .map>((TileOverlay p) => p.toJson()) + .toList(); +} diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/platform_interface/google_maps_flutter_platform_test.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/platform_interface/google_maps_flutter_platform_test.dart index a003b94d544c..582acea54dd1 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/platform_interface/google_maps_flutter_platform_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/platform_interface/google_maps_flutter_platform_test.dart @@ -45,14 +45,11 @@ void main() { log.add(methodCall); }); -// final MethodChannelGoogleMapsFlutter map = MethodChannelGoogleMapsFlutter(0); - tearDown(() { log.clear(); }); test('foo', () async { -// await map.foo(); expect( log, [], 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 new file mode 100644 index 000000000000..246a71096157 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_overlay_test.dart @@ -0,0 +1,124 @@ +// 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'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('tile overlay id tests', () { + test('equality', () async { + final TileOverlayId id1 = TileOverlayId('1'); + final TileOverlayId id2 = TileOverlayId('1'); + final TileOverlayId id3 = TileOverlayId('2'); + expect(id1, id2); + expect(id1, isNot(id3)); + }); + + test('toString', () async { + final TileOverlayId id1 = TileOverlayId('1'); + expect(id1.toString(), 'TileOverlay{value: 1}'); + }); + }); + + group('tile overlay tests', () { + test('toJson returns correct format', () async { + final TileOverlay tileOverlay = TileOverlay( + tileOverlayId: TileOverlayId('id'), + fadeIn: false, + tileProvider: null, + transparency: 0.1, + zIndex: 1, + visible: false, + tileSize: 128); + final Map 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); + }); + + test('invalid transparency throws', () async { + expect( + () => TileOverlay( + tileOverlayId: TileOverlayId('id1'), transparency: -0.1), + throwsAssertionError); + expect( + () => TileOverlay( + tileOverlayId: TileOverlayId('id2'), transparency: 1.2), + throwsAssertionError); + }); + + test('equality', () async { + final TileOverlay tileOverlay1 = TileOverlay( + tileOverlayId: TileOverlayId('id1'), + fadeIn: false, + tileProvider: null, + transparency: 0.1, + zIndex: 1, + visible: false, + tileSize: 128); + final TileOverlay tileOverlay2 = TileOverlay( + tileOverlayId: TileOverlayId('id1'), + fadeIn: false, + tileProvider: null, + transparency: 0.1, + zIndex: 1, + visible: false, + tileSize: 128); + final TileOverlay tileOverlay3 = TileOverlay( + tileOverlayId: TileOverlayId('id2'), + fadeIn: false, + tileProvider: null, + transparency: 0.1, + zIndex: 1, + visible: false, + tileSize: 128); + expect(tileOverlay1, tileOverlay2); + expect(tileOverlay1, isNot(tileOverlay3)); + }); + + test('hashCode', () async { + TileOverlayId id = TileOverlayId('id1'); + final TileOverlay tileOverlay = TileOverlay( + tileOverlayId: id, + fadeIn: false, + tileProvider: null, + transparency: 0.1, + zIndex: 1, + visible: false, + tileSize: 128); + expect(tileOverlay.hashCode, id.hashCode); + }); + }); + + group('tile overlay utils tests', () { + test('keyTileOverlayId', () async { + final TileOverlay tileOverlay1 = + TileOverlay(tileOverlayId: TileOverlayId('id1')); + final TileOverlay tileOverlay2 = + TileOverlay(tileOverlayId: TileOverlayId('id2')); + final Map result = + keyTileOverlayId([tileOverlay1, tileOverlay2]); + expect(result[TileOverlayId('id1')], tileOverlay1); + expect(result[TileOverlayId('id2')], tileOverlay2); + }); + + test('serializeTileOverlaySet', () async { + final TileOverlay tileOverlay1 = + TileOverlay(tileOverlayId: TileOverlayId('id1')); + final TileOverlay tileOverlay2 = + TileOverlay(tileOverlayId: TileOverlayId('id2')); + final Set tileOverlaySet = + Set.from([tileOverlay1, tileOverlay2]); + List> result = + serializeTileOverlaySet(tileOverlaySet); + expect(result[0]['tileOverlayId'], 'id1'); + expect(result[1]['tileOverlayId'], 'id2'); + }); + }); +} 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 new file mode 100644 index 000000000000..3708d1b5823b --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_overlay_updates_test.dart @@ -0,0 +1,121 @@ +// 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'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('tile overlay updates tests', () { + test('Correctly set toRemove, toAdd and toChange', () async { + final TileOverlay to1 = TileOverlay(tileOverlayId: TileOverlayId('id1')); + final TileOverlay to2 = TileOverlay(tileOverlayId: TileOverlayId('id2')); + final TileOverlay to3 = TileOverlay(tileOverlayId: TileOverlayId('id3')); + final TileOverlay to3Changed = + TileOverlay(tileOverlayId: TileOverlayId('id3'), transparency: 0.5); + final TileOverlay to4 = TileOverlay(tileOverlayId: TileOverlayId('id4')); + final Set previous = Set.from([to1, to2, to3]); + final Set current = + Set.from([to2, to3Changed, to4]); + final TileOverlayUpdates updates = + TileOverlayUpdates.from(previous, current); + + final Set toRemove = + Set.from([TileOverlayId('id1')]); + expect(updates.tileOverlayIdsToRemove, toRemove); + + final Set toAdd = Set.from([to4]); + expect(updates.tileOverlaysToAdd, toAdd); + + final Set toChange = Set.from([to3Changed]); + expect(updates.tileOverlaysToChange, toChange); + }); + + test('toJson', () async { + final TileOverlay to1 = TileOverlay(tileOverlayId: TileOverlayId('id1')); + final TileOverlay to2 = TileOverlay(tileOverlayId: TileOverlayId('id2')); + final TileOverlay to3 = TileOverlay(tileOverlayId: TileOverlayId('id3')); + final TileOverlay to3Changed = + TileOverlay(tileOverlayId: TileOverlayId('id3'), transparency: 0.5); + final TileOverlay to4 = TileOverlay(tileOverlayId: TileOverlayId('id4')); + final Set previous = Set.from([to1, to2, to3]); + final Set current = + Set.from([to2, to3Changed, to4]); + final TileOverlayUpdates updates = + TileOverlayUpdates.from(previous, current); + + final Map json = updates.toJson(); + expect(json, { + 'tileOverlaysToAdd': serializeTileOverlaySet(updates.tileOverlaysToAdd), + 'tileOverlaysToChange': + serializeTileOverlaySet(updates.tileOverlaysToChange), + 'tileOverlayIdsToRemove': updates.tileOverlayIdsToRemove + .map((TileOverlayId m) => m.value) + .toList() + }); + }); + + test('equality', () async { + final TileOverlay to1 = TileOverlay(tileOverlayId: TileOverlayId('id1')); + final TileOverlay to2 = TileOverlay(tileOverlayId: TileOverlayId('id2')); + final TileOverlay to3 = TileOverlay(tileOverlayId: TileOverlayId('id3')); + final TileOverlay to3Changed = + TileOverlay(tileOverlayId: TileOverlayId('id3'), transparency: 0.5); + final TileOverlay to4 = TileOverlay(tileOverlayId: TileOverlayId('id4')); + final Set previous = Set.from([to1, to2, to3]); + final Set current1 = + Set.from([to2, to3Changed, to4]); + final Set current2 = + Set.from([to2, to3Changed, to4]); + final Set current3 = Set.from([to2, to4]); + final TileOverlayUpdates updates1 = + TileOverlayUpdates.from(previous, current1); + final TileOverlayUpdates updates2 = + TileOverlayUpdates.from(previous, current2); + final TileOverlayUpdates updates3 = + TileOverlayUpdates.from(previous, current3); + expect(updates1, updates2); + expect(updates1, isNot(updates3)); + }); + + test('hashCode', () async { + final TileOverlay to1 = TileOverlay(tileOverlayId: TileOverlayId('id1')); + final TileOverlay to2 = TileOverlay(tileOverlayId: TileOverlayId('id2')); + final TileOverlay to3 = TileOverlay(tileOverlayId: TileOverlayId('id3')); + final TileOverlay to3Changed = + TileOverlay(tileOverlayId: TileOverlayId('id3'), transparency: 0.5); + final TileOverlay to4 = TileOverlay(tileOverlayId: TileOverlayId('id4')); + final Set previous = Set.from([to1, to2, to3]); + final Set current = + Set.from([to2, to3Changed, to4]); + final TileOverlayUpdates updates = + TileOverlayUpdates.from(previous, current); + expect( + updates.hashCode, + updates.tileOverlaysToAdd.hashCode ^ + updates.tileOverlayIdsToRemove.hashCode ^ + updates.tileOverlaysToChange.hashCode); + }); + + test('toString', () async { + final TileOverlay to1 = TileOverlay(tileOverlayId: TileOverlayId('id1')); + final TileOverlay to2 = TileOverlay(tileOverlayId: TileOverlayId('id2')); + final TileOverlay to3 = TileOverlay(tileOverlayId: TileOverlayId('id3')); + final TileOverlay to3Changed = + TileOverlay(tileOverlayId: TileOverlayId('id3'), transparency: 0.5); + final TileOverlay to4 = TileOverlay(tileOverlayId: TileOverlayId('id4')); + final Set previous = Set.from([to1, to2, to3]); + final Set current = + Set.from([to2, to3Changed, to4]); + final TileOverlayUpdates updates = + TileOverlayUpdates.from(previous, current); + expect( + updates.toString(), + 'TileOverlayUpdates{tileOverlaysToAdd: ${updates.tileOverlaysToAdd}, ' + 'tileOverlayIdsToRemove: ${updates.tileOverlayIdsToRemove}, ' + 'tileOverlaysToChange: ${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 new file mode 100644 index 000000000000..0be9a7cea8f0 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/tile_test.dart @@ -0,0 +1,28 @@ +// 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:typed_data'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('tile tests', () { + test('toJson returns correct format', () async { + final Uint8List data = Uint8List.fromList([0, 1]); + final Tile tile = Tile(100, 200, data); + final Map json = tile.toJson(); + expect(json['width'], 100); + expect(json['height'], 200); + expect(json['data'], data); + }); + + test('toJson returns empty if nothing presents', () async { + final Tile tile = Tile(null, null, null); + final Map json = tile.toJson(); + expect(json.isEmpty, true); + }); + }); +} From 54c8baa2632f8976e9d3f44de844a5ab51e579c2 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 14 Jan 2021 12:45:44 -0800 Subject: [PATCH 2/7] review --- .../lib/src/types/tile.dart | 2 +- .../lib/src/types/tile_overlay.dart | 47 ++++++++++--------- .../lib/src/types/tile_overlay_updates.dart | 29 +++++------- .../lib/src/types/tile_provider.dart | 2 + .../test/types/tile_overlay_test.dart | 5 +- .../test/types/tile_overlay_updates_test.dart | 12 ++--- 6 files changed, 48 insertions(+), 49 deletions(-) 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 38c9e69de38e..3f4ff9fc948e 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,7 +21,7 @@ class Tile { final Uint8List data; /// Converts this object to JSON. - dynamic toJson() { + Map toJson() { final Map json = {}; void addIfPresent(String fieldName, dynamic 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 824bd80b6208..0f9875587ef8 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 @@ -2,12 +2,13 @@ // 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'; + import 'types.dart'; import 'package:meta/meta.dart' show immutable, required; /// Uniquely identifies a [TileOverlay] among [GoogleMap] tile overlays. -/// -/// This does not have to be globally unique, only unique among the list. @immutable class TileOverlayId { /// Creates an immutable identifier for a [TileOverlay]. @@ -18,25 +19,24 @@ class TileOverlayId { @override bool operator ==(Object other) { - if (identical(this, other)) return true; - if (other.runtimeType != runtimeType) return false; - final TileOverlayId typedOther = other; - return value == typedOther.value; + if (other.runtimeType != runtimeType) { + return false; + } + return other is TileOverlayId && other.value == value; } @override int get hashCode => value.hashCode; @override - String toString() { - return 'TileOverlay{value: $value}'; - } + String toString() => '${objectRuntimeType(this, 'TileOverlayId')}($value)'; } -/// A Tile Overlay is a set of images which are displayed on top of the base map tiles. +/// # A set of images which are displayed on top of the base map tiles. +/// /// These tiles may be transparent, allowing you to add features to existing maps. /// -/// Tile Coordinates +/// ## Tile Coordinates /// /// Note that the world is projected using the Mercator projection /// (see [Wikipedia](https://en.wikipedia.org/wiki/Mercator_projection)) with the left (west) side @@ -101,7 +101,7 @@ class TileOverlay { /// would give on a non-retina device. final int tileSize; - /// Creates a new [Polygon] object whose values are the same as this instance, + /// Creates a new [TileOverlay] object whose values are the same as this instance, /// unless overwritten by the specified parameters. TileOverlay copyWith({ TileOverlayId tileOverlayId, @@ -122,7 +122,7 @@ class TileOverlay { } /// Converts this object to JSON. - dynamic toJson() { + Map toJson() { final Map json = {}; void addIfPresent(String fieldName, dynamic value) { @@ -143,17 +143,18 @@ class TileOverlay { @override bool operator ==(Object other) { - if (identical(this, other)) return true; - if (other.runtimeType != runtimeType) return false; - final TileOverlay typedOther = other; - return tileOverlayId == typedOther.tileOverlayId && - fadeIn == typedOther.fadeIn && - transparency == typedOther.transparency && - zIndex == typedOther.zIndex && - visible == typedOther.visible && - tileSize == typedOther.tileSize; + if (other.runtimeType != runtimeType) { + return false; + } + return other is TileOverlay + && tileOverlayId == other.tileOverlayId + && fadeIn == other.fadeIn + && transparency == other.transparency + && zIndex == other.zIndex + && visible == other.visible + && tileSize == other.tileSize; } @override - int get hashCode => tileOverlayId.hashCode; + int get hashCode => hashValues(tileOverlayId, fadeIn, transparency, zIndex, visible, tileSize); } 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 9b6e096cd981..69386dfd731d 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,12 +2,13 @@ // 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 setEquals; +import 'package:flutter/foundation.dart' show objectRuntimeType, setEquals; +import 'dart:ui' show hashValues, hashList; import 'utils/tile_overlay.dart'; import 'types.dart'; -/// Represents the details of an update events of [TileOverlay]s. +/// Update specification for a set of [TileOverlay]s. class TileOverlayUpdates { /// Computes [TileOverlayUpdates] given previous and current [TileOverlay]s. TileOverlayUpdates.from(Set previous, Set current) { @@ -101,25 +102,21 @@ class TileOverlayUpdates { @override bool operator ==(Object other) { - if (identical(this, other)) return true; - if (other.runtimeType != runtimeType) return false; - final TileOverlayUpdates typedOther = other; - return setEquals(_tileOverlaysToAdd, typedOther._tileOverlaysToAdd) && - setEquals( - _tileOverlayIdsToRemove, typedOther._tileOverlayIdsToRemove) && - setEquals(_tileOverlaysToChange, typedOther._tileOverlaysToChange); + 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 => - _tileOverlaysToAdd.hashCode ^ - _tileOverlayIdsToRemove.hashCode ^ - _tileOverlaysToChange.hashCode; + int get hashCode => hashValues(hashList(_tileOverlaysToAdd), hashList(_tileOverlayIdsToRemove), hashList(_tileOverlaysToChange)); @override String toString() { - return 'TileOverlayUpdates{tileOverlaysToAdd: $_tileOverlaysToAdd, ' - 'tileOverlayIdsToRemove: $_tileOverlayIdsToRemove, ' - 'tileOverlaysToChange: $_tileOverlaysToChange}'; + return '${objectRuntimeType(this, 'TileOverlayUpdates')}($_tileOverlaysToAdd, $_tileOverlayIdsToRemove, $_tileOverlaysToChange)'; } } 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 f0754159c941..c3c4f807e283 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 @@ -10,5 +10,7 @@ abstract class TileProvider { static const Tile noTile = Tile(-1, -1, null); /// Returns the tile to be used for this tile coordinate. + /// + /// See [TileOverlay] for the specification of tile coordinates. Future getTile(int x, int y, int zoom); } 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 246a71096157..ad1e67e43116 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 @@ -2,6 +2,7 @@ // 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_test/flutter_test.dart'; import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; @@ -19,7 +20,7 @@ void main() { test('toString', () async { final TileOverlayId id1 = TileOverlayId('1'); - expect(id1.toString(), 'TileOverlay{value: 1}'); + expect(id1.toString(), 'TileOverlayId(1)'); }); }); @@ -92,7 +93,7 @@ void main() { zIndex: 1, visible: false, tileSize: 128); - expect(tileOverlay.hashCode, id.hashCode); + expect(tileOverlay.hashCode, hashValues(tileOverlay.tileOverlayId, tileOverlay.fadeIn, tileOverlay.transparency, tileOverlay.zIndex, tileOverlay.visible, tileOverlay.tileSize)); }); }); 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 3708d1b5823b..1deb5429e1b3 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 @@ -2,6 +2,7 @@ // 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_test/flutter_test.dart'; import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; @@ -93,10 +94,7 @@ void main() { final TileOverlayUpdates updates = TileOverlayUpdates.from(previous, current); expect( - updates.hashCode, - updates.tileOverlaysToAdd.hashCode ^ - updates.tileOverlayIdsToRemove.hashCode ^ - updates.tileOverlaysToChange.hashCode); + updates.hashCode, hashValues(hashList(updates.tileOverlaysToAdd), hashList(updates.tileOverlayIdsToRemove), hashList(updates.tileOverlaysToChange))); }); test('toString', () async { @@ -113,9 +111,9 @@ void main() { TileOverlayUpdates.from(previous, current); expect( updates.toString(), - 'TileOverlayUpdates{tileOverlaysToAdd: ${updates.tileOverlaysToAdd}, ' - 'tileOverlayIdsToRemove: ${updates.tileOverlayIdsToRemove}, ' - 'tileOverlaysToChange: ${updates.tileOverlaysToChange}}'); + 'TileOverlayUpdates(${updates.tileOverlaysToAdd}, ' + '${updates.tileOverlayIdsToRemove}, ' + '${updates.tileOverlaysToChange})'); }); }); } From 899e2e7ca31d6ae377b597832e3316ac5a882ab7 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 14 Jan 2021 14:05:57 -0800 Subject: [PATCH 3/7] fix --- .../src/platform_interface/google_maps_flutter_platform.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a1a6c87f3289..9c39236394a1 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 @@ -17,7 +17,7 @@ import 'package:plugin_platform_interface/plugin_platform_interface.dart'; /// Callback method for when a [Tile] is requested from a [TileProvider]. typedef Future MapGetTileCallback( - TileOverlayId tileOverlayId, int x, int y, int zoom); + String tileOverlayIdString, int x, int y, int zoom); /// The interface that platform-specific implementations of `google_maps_flutter` must extend. /// From fd319cc6500640c2eb378d78b531351fb68821df Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 14 Jan 2021 15:24:59 -0800 Subject: [PATCH 4/7] reviews and formats --- .../lib/src/types/tile.dart | 4 ++-- .../lib/src/types/tile_overlay.dart | 19 ++++++++++--------- .../lib/src/types/tile_overlay_updates.dart | 12 ++++++------ .../test/types/tile_overlay_test.dart | 10 +++++++++- .../test/types/tile_overlay_updates_test.dart | 6 +++++- 5 files changed, 32 insertions(+), 19 deletions(-) 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 3f4ff9fc948e..39666744224c 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 @@ -11,10 +11,10 @@ class Tile { /// Creates an immutable representation of a [Tile] to draw by [TileProvider]. const Tile(this.width, this.height, this.data); - /// The width of the image encoded by data in pixels. + /// The width of the image encoded by data in logical pixels. final int width; - /// The height of the image encoded by data in pixels. + /// The height of the image encoded by data in logical pixels. final int height; /// A byte array containing the image data. 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 0f9875587ef8..13950287ff75 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 @@ -92,7 +92,7 @@ class TileOverlay { /// The visibility for the tile overlay. The default visibility is true. final bool visible; - /// Specifies the number of pixels (not points) that the returned tile images will prefer + /// Specifies the number of logical pixels (not points) that the returned tile images will prefer /// to display as. iOS only. /// /// Defaults to 256, which is the traditional size of Google Maps tiles. @@ -146,15 +146,16 @@ class TileOverlay { if (other.runtimeType != runtimeType) { return false; } - return other is TileOverlay - && tileOverlayId == other.tileOverlayId - && fadeIn == other.fadeIn - && transparency == other.transparency - && zIndex == other.zIndex - && visible == other.visible - && tileSize == other.tileSize; + return other is TileOverlay && + tileOverlayId == other.tileOverlayId && + fadeIn == other.fadeIn && + transparency == other.transparency && + zIndex == other.zIndex && + visible == other.visible && + tileSize == other.tileSize; } @override - int get hashCode => hashValues(tileOverlayId, fadeIn, transparency, zIndex, visible, tileSize); + int get hashCode => hashValues( + tileOverlayId, fadeIn, transparency, zIndex, visible, tileSize); } 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 69386dfd731d..2910fc37d495 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 @@ -105,15 +105,15 @@ class TileOverlayUpdates { if (other.runtimeType != runtimeType) { return false; } - return other is TileOverlayUpdates - && setEquals(_tileOverlaysToAdd, other._tileOverlaysToAdd) - && setEquals( - _tileOverlayIdsToRemove, other._tileOverlayIdsToRemove) - && setEquals(_tileOverlaysToChange, other._tileOverlaysToChange); + 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)); + int get hashCode => hashValues(hashList(_tileOverlaysToAdd), + hashList(_tileOverlayIdsToRemove), hashList(_tileOverlaysToChange)); @override String toString() { 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 ad1e67e43116..84bbdb43b36a 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 @@ -93,7 +93,15 @@ void main() { zIndex: 1, visible: false, tileSize: 128); - expect(tileOverlay.hashCode, hashValues(tileOverlay.tileOverlayId, tileOverlay.fadeIn, tileOverlay.transparency, tileOverlay.zIndex, tileOverlay.visible, tileOverlay.tileSize)); + expect( + tileOverlay.hashCode, + hashValues( + tileOverlay.tileOverlayId, + tileOverlay.fadeIn, + tileOverlay.transparency, + tileOverlay.zIndex, + tileOverlay.visible, + tileOverlay.tileSize)); }); }); 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 1deb5429e1b3..63215a5a50e2 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 @@ -94,7 +94,11 @@ void main() { final TileOverlayUpdates updates = TileOverlayUpdates.from(previous, current); expect( - updates.hashCode, hashValues(hashList(updates.tileOverlaysToAdd), hashList(updates.tileOverlayIdsToRemove), hashList(updates.tileOverlaysToChange))); + updates.hashCode, + hashValues( + hashList(updates.tileOverlaysToAdd), + hashList(updates.tileOverlayIdsToRemove), + hashList(updates.tileOverlaysToChange))); }); test('toString', () async { From e96e15e2caa225fef42779e16cea592674ef3b42 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 21 Jan 2021 12:16:13 -0800 Subject: [PATCH 5/7] reviews --- .../method_channel_google_maps_flutter.dart | 9 ++++++--- .../platform_interface/google_maps_flutter_platform.dart | 6 ++++-- .../lib/src/types/tile.dart | 2 ++ .../lib/src/types/tile_overlay.dart | 4 ++-- 4 files changed, 14 insertions(+), 7 deletions(-) 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 c22278e59776..2a891ca6bcea 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 @@ -189,7 +189,8 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform { )); break; case 'tileOverlay#getTile': - final getTileCallback = _getTileCallbacks[mapId]; + final MapGetTileCallback getTileCallback = _getTileCallbacks[mapId]; + assert(getTileCallback != null); final Tile tile = await getTileCallback( call.arguments['tileOverlayId'], call.arguments['x'], @@ -313,8 +314,10 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform { } /// 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 API maintains a small + /// [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 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 9c39236394a1..5c6052b34751 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 @@ -133,8 +133,10 @@ abstract class GoogleMapsFlutterPlatform extends PlatformInterface { } /// 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 API maintains a small + /// [TileProvider]. + /// + /// The current tiles from this tile overlay will also be + /// cleared from the map after calling this method. The Google Maps SDK maintains a small /// in-memory cache of tiles. If you want to cache tiles for longer, you /// should implement an on-disk cache. Future clearTileCache( 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 39666744224c..e3dc5fe4d8b2 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 @@ -18,6 +18,8 @@ class Tile { final int height; /// A byte array containing the image data. + /// + /// The image data format accepted by platforms various based on platforms and versions. final Uint8List data; /// Converts this object to JSON. 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 13950287ff75..3978f23f05f8 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 @@ -14,7 +14,7 @@ class TileOverlayId { /// Creates an immutable identifier for a [TileOverlay]. TileOverlayId(this.value) : assert(value != null); - /// value of the [TileOverlayId]. + /// The value of the [TileOverlayId]. final String value; @override @@ -32,7 +32,7 @@ class TileOverlayId { String toString() => '${objectRuntimeType(this, 'TileOverlayId')}($value)'; } -/// # A set of images which are displayed on top of the base map tiles. +/// A set of images which are displayed on top of the base map tiles. /// /// These tiles may be transparent, allowing you to add features to existing maps. /// From ed30f8bc1df93460c0f3ea78fc51b31a6748efb7 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 21 Jan 2021 13:13:57 -0800 Subject: [PATCH 6/7] cache tileOverlays --- .../method_channel_google_maps_flutter.dart | 20 +++++++++---------- .../google_maps_flutter_platform.dart | 8 +++++--- 2 files changed, 14 insertions(+), 14 deletions(-) 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 2a891ca6bcea..df7b6d07fdc4 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 @@ -33,9 +33,8 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform { return _channels[mapId]; } - // Keep a collection of id -> GetTileCallback - // Every method call passes the int mapId - final Map _getTileCallbacks = {}; + // Keep a collection of id -> TileOverlay. + final Map _tileOverlays = {}; /// Initializes the platform interface with [id]. /// @@ -189,10 +188,9 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform { )); break; case 'tileOverlay#getTile': - final MapGetTileCallback getTileCallback = _getTileCallbacks[mapId]; - assert(getTileCallback != null); - final Tile tile = await getTileCallback( - call.arguments['tileOverlayId'], + final TileOverlay tileOverlay = _tileOverlays[mapId]; + assert(tileOverlay.tileProvider != null); + final Tile tile = await tileOverlay.tileProvider.getTile( call.arguments['x'], call.arguments['y'], call.arguments['zoom'], @@ -505,10 +503,10 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform { /// /// `mapId` and `callback` must not be null. @override - void setGetTileCallback( - {@required int mapId, @required MapGetTileCallback callback}) { - assert(mapId != null && callback != null); - _getTileCallbacks[mapId] = callback; + void setTileOverlay( + {@required int mapId, @required TileOverlay tileOverlay}) { + assert(mapId != null && tileOverlay != null); + _tileOverlays[mapId] = tileOverlay; } /// This method builds the appropriate platform view where the map 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 5c6052b34751..93cda7c4749f 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 @@ -277,9 +277,11 @@ abstract class GoogleMapsFlutterPlatform extends PlatformInterface { throw UnimplementedError('takeSnapshot() has not been implemented.'); } - /// Set the [MapGetTileCallback] for the map, which will be called - /// when a [Tile] is requested for an added [TileProvider]. - void setGetTileCallback({@required int mapId, MapGetTileCallback callback}) { + /// Set the [TileOverlay] for the map. + /// + /// The [TileProvider] is called when a [Tile] is requested. + void setTileOverlay( + {@required int mapId, @required TileOverlay tileOverlay}) { throw UnimplementedError('onGetTile() has not been implemented.'); } From 6ceb6edd4f2cdfbff640e6f0c16255f304ca06e7 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 21 Jan 2021 13:17:29 -0800 Subject: [PATCH 7/7] update assert --- .../src/method_channel/method_channel_google_maps_flutter.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 df7b6d07fdc4..74420f97cd6b 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 @@ -189,7 +189,7 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform { break; case 'tileOverlay#getTile': final TileOverlay tileOverlay = _tileOverlays[mapId]; - assert(tileOverlay.tileProvider != null); + assert(tileOverlay.tileProvider.getTile != null); final Tile tile = await tileOverlay.tileProvider.getTile( call.arguments['x'], call.arguments['y'],