-
Notifications
You must be signed in to change notification settings - Fork 4
[DO NOT MERGE] Add BitmapRegistry #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
1098e79
bdd65ab
774ffae
140dbb2
94fbf0c
5b8555b
06b40c2
0f13881
e8a25eb
d19b6c9
08a408b
ebfb4eb
2e2bf8d
49d9a05
c7518ee
bd53fba
9799b6a
dcf3876
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| // Copyright 2013 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| // ignore_for_file: public_member_api_docs | ||
|
|
||
| import 'dart:math'; | ||
|
|
||
| import 'package:flutter/material.dart'; | ||
| import 'package:flutter/services.dart'; | ||
| import 'package:google_maps_flutter/google_maps_flutter.dart'; | ||
| import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; | ||
|
|
||
| import 'page.dart'; | ||
|
|
||
| class BitmapRegistryPage extends GoogleMapExampleAppPage { | ||
| const BitmapRegistryPage({Key? key}) | ||
| : super(const Icon(Icons.speed), 'Bitmap registry', key: key); | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| return const _BitmapRegistryBody(); | ||
| } | ||
| } | ||
|
|
||
| // How many markers to place on the map. | ||
| const int _numberOfMarkers = 500; | ||
|
|
||
| // The name of the bitmap to use for the markers. | ||
| const String _bitmapName = 'assets/checkers.png'; | ||
|
|
||
| class _BitmapRegistryBody extends StatefulWidget { | ||
| const _BitmapRegistryBody(); | ||
|
|
||
| @override | ||
| State<_BitmapRegistryBody> createState() => _BitmapRegistryBodyState(); | ||
| } | ||
|
|
||
| class _BitmapRegistryBodyState extends State<_BitmapRegistryBody> { | ||
| final Set<Marker> markers = <Marker>{}; | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| return SingleChildScrollView( | ||
| child: Column( | ||
| children: <Widget>[ | ||
| AspectRatio( | ||
| aspectRatio: 2 / 3, | ||
| child: GoogleMap( | ||
| markers: markers, | ||
| initialCameraPosition: const CameraPosition( | ||
| target: LatLng(0, 0), | ||
| zoom: 1.0, | ||
| ), | ||
| ), | ||
| ), | ||
| MaterialButton( | ||
| onPressed: _addMarkersWithoutRegistry, | ||
| child: const Text('Add $_numberOfMarkers markers, no registry'), | ||
| ), | ||
| MaterialButton( | ||
| onPressed: _addMarkersWithRegistry, | ||
| child: const Text('Add $_numberOfMarkers markers using registry'), | ||
| ), | ||
| ], | ||
| ), | ||
| ); | ||
| } | ||
|
|
||
| /// Add markers to the map with a custom bitmap as the icon. | ||
| /// | ||
| /// To show potential performance issues: | ||
| /// * large original image is used (800x600px, ~330KB) | ||
| /// * bitmap is scaled down to 64x64px | ||
| /// * bitmap is created once and reused for all markers. This doesn't help | ||
| /// much because the bitmap is still sent to the platform side for each | ||
| /// marker. | ||
| /// | ||
| /// Adding many markers may result in a performance hit, out of memory errors | ||
| /// or even app crashes. | ||
| Future<void> _addMarkersWithoutRegistry() async { | ||
| final ByteData byteData = await rootBundle.load(_bitmapName); | ||
| final Uint8List bytes = byteData.buffer.asUint8List(); | ||
| final BytesMapBitmap bitmap = BitmapDescriptor.bytes( | ||
| bytes, | ||
| width: 64, | ||
| height: 64, | ||
| ); | ||
| _updateMarkers(bitmap); | ||
| } | ||
|
|
||
| /// Add markers to the map with a custom bitmap as the icon placed in the | ||
| /// bitmap registry beforehand. | ||
| /// | ||
| /// Similarly to [_addMarkersWithoutRegistry], this method uses the same | ||
| /// technique to show potential performance issues, however the bitmap is | ||
| /// registered in the bitmap registry before creating the markers. | ||
| Future<void> _addMarkersWithRegistry() async { | ||
| final ByteData byteData = await rootBundle.load(_bitmapName); | ||
| final Uint8List bytes = byteData.buffer.asUint8List(); | ||
| final BytesMapBitmap bytesBitmap = BitmapDescriptor.bytes( | ||
| bytes, | ||
| width: 64, | ||
| height: 64, | ||
| ); | ||
| final int registeredBitmapId = | ||
| await GoogleMapBitmapRegistry.instance.register(bytesBitmap); | ||
| final RegisteredMapBitmap registeredBitmap = | ||
| RegisteredMapBitmap(id: registeredBitmapId); | ||
| _updateMarkers(registeredBitmap); | ||
| } | ||
|
|
||
| // Create a set of markers with the given bitmap and update the state with new | ||
| // markers. | ||
| void _updateMarkers(BitmapDescriptor bitmap) { | ||
| final List<Marker> newMarkers = List<Marker>.generate( | ||
| _numberOfMarkers, | ||
| (int id) { | ||
| return Marker( | ||
| markerId: MarkerId('$id'), | ||
| icon: bitmap, | ||
| position: LatLng( | ||
| Random().nextDouble() * 100 - 50, | ||
| Random().nextDouble() * 100 - 50, | ||
| ), | ||
| ); | ||
| }, | ||
| ); | ||
|
|
||
| setState(() { | ||
| markers | ||
| ..clear() | ||
| ..addAll(newMarkers); | ||
| }); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| part of '../google_maps_flutter.dart'; | ||
|
|
||
| /// A bitmap registry. | ||
| /// | ||
| /// Bitmaps can be created before they are used in markers and then registered | ||
| /// with the registry. This allows for more efficient rendering of markers | ||
| /// on the map. For example, if multiple markers use the same bitmap, bitmap | ||
| /// can be registered once and then reused. This eliminates the need to | ||
| /// transfer the bitmap data multiple times to the platform side. | ||
| /// | ||
| /// Using bitmap registry is optional. | ||
| /// | ||
| /// Bitmap registry can be used after the map is initialized and displayed | ||
| /// on the screen. On Android registry can be also used after map renderer is | ||
| /// initialized without map being displayed on the screen. | ||
| /// | ||
| /// Example: | ||
| /// ```dart | ||
| /// // Register a bitmap | ||
| /// final registeredBitmap = await GoogleMapBitmapRegistry.instance.register( | ||
| /// Bitmap.fromAsset('assets/image.png'), | ||
| /// ); | ||
| /// | ||
| /// // Use the registered bitmap as marker icon | ||
| /// Marker( | ||
| /// markerId: MarkerId('markerId'), | ||
| /// icon: registeredBitmap, | ||
| /// position: LatLng(0, 0) | ||
| /// ), | ||
| /// ) | ||
| /// ``` | ||
| class GoogleMapBitmapRegistry { | ||
| GoogleMapBitmapRegistry._(); | ||
|
|
||
| /// The singleton instance of [GoogleMapBitmapRegistry]. | ||
| static final GoogleMapBitmapRegistry instance = GoogleMapBitmapRegistry._(); | ||
|
|
||
| // The number of registered images. Also used as a unique identifier for each | ||
| // registered image. | ||
| int _imageCount = 0; | ||
|
|
||
| /// Registers a [bitmap] with the registry. | ||
| /// | ||
| /// Returns a unique identifier for the registered bitmap. | ||
| Future<int> register(MapBitmap bitmap) async { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this could return RegisteredMapBitmap object directly
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is what I was doing initially but then there was a comment to my other PR about not mixing platform and user-facing packages. I think it will be the case here too because I see these options:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, BitmapDescriptor classes are used already as icon objects etc.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIR it was about using platform interface's I'd rather keep it like it is now and wait for review or ask a question when main PR is created. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it is quite easy to change later if they want to |
||
| _imageCount++; | ||
| final int id = _imageCount; | ||
| await GoogleMapsFlutterPlatform.instance.registerBitmap(id, bitmap); | ||
| return id; | ||
| } | ||
|
|
||
| /// Unregisters a bitmap with the given [id]. | ||
| Future<void> unregister(int id) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this take RegisteredMapBitmap as a parameter. |
||
| return GoogleMapsFlutterPlatform.instance.unregisterBitmap(id); | ||
| } | ||
|
|
||
| /// Unregister all previously registered bitmaps and clear the cache. | ||
| Future<void> clear() { | ||
| return GoogleMapsFlutterPlatform.instance.clearBitmapCache(); | ||
| } | ||
| } | ||
|
aednlaxer marked this conversation as resolved.
|
Uh oh!
There was an error while loading. Please reload this page.