Skip to content

[google_maps_flutter] Add missing exports#11196

Open
stuartmorgan-g wants to merge 1 commit intoflutter:mainfrom
stuartmorgan-g:maps-advanced-marker-export
Open

[google_maps_flutter] Add missing exports#11196
stuartmorgan-g wants to merge 1 commit intoflutter:mainfrom
stuartmorgan-g:maps-advanced-marker-export

Conversation

@stuartmorgan-g
Copy link
Collaborator

This adds exports that should have been in #7882, but I missed in review.

Like much of the google_maps_flutter APIs currently, advanced markers rely on clients using types that are defined in the platform interface package. This re-exports them, and fixes the examples to not import the platform interface.

Ideally we would have more separation between the API layers, but this is deeply ingrained in the API design of the plugin at this point, so changing it would require a comprehensive overhaul.

Pre-Review Checklist

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. 2

Like much of the `google_maps_flutter` APIs currently, advanced markers
rely on clients using types that are defined in the platform interface
package. This re-exports them, and fixes the examples to not import the
platform interface.

Ideally we would have more separation between the API layers, but this
is deeply ingrained in the API design of the plugin at this point, so
changing it would require a comprehensive overhaul.
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly adds missing re-exports for advanced marker-related classes from the google_maps_flutter_platform_interface package into the main google_maps_flutter package. The example files have been updated to reflect these changes by removing direct imports from the platform interface, which improves the API's consistency and usability. The changelog and pubspec.yaml have also been updated appropriately. The changes are well-aligned with the pull request's objective.

@stuartmorgan-g
Copy link
Collaborator Author

@jokerttu I ran into one potentially thorn issue here that I completely missed in review: one of the example pages is calling GoogleMapsFlutterPlatform.instance.isAdvancedMarkersAvailable and I can't remove that because there's no passthrough from the app-facing package. I was going to add one, but then I noticed that it takes a map ID. But the only way to get a map ID is to have made a MapWidget. And the marker type is a parameter to the MapWidget constructor.

Don't clients need to know whether advanced marker support is available before passing the advanced marker type to MapWidget? Is it a mistake in the platform interface that the query takes a map ID?

Copy link
Contributor

@bparrishMines bparrishMines left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM pending test question


export 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'
show
AdvancedMarker,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I'll add that so we don't regress on any future refactorings.

Copy link
Contributor

@tarrinneal tarrinneal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good rule of thumb, apps shouldn't be importing the platform interface if they are only using the primary plugin?

@jokerttu
Copy link
Contributor

jokerttu commented Mar 19, 2026

@stuartmorgan-g

@jokerttu I ran into one potentially thorn issue here that I completely missed in review: one of the example pages is calling GoogleMapsFlutterPlatform.instance.isAdvancedMarkersAvailable and I can't remove that because there's no passthrough from the app-facing package. I was going to add one, but then I noticed that it takes a map ID. But the only way to get a map ID is to have made a MapWidget. And the marker type is a parameter to the MapWidget constructor.

Don't clients need to know whether advanced marker support is available before passing the advanced marker type to MapWidget? Is it a mistake in the platform interface that the query takes a map ID?

You are absolutely right; there is indeed a chicken-and-egg problem here. I completely missed this too when I took over the implementation PR.

Since this design flaw has already landed, here is my suggestion::

We could implement new GoogleMapsFlutterPlatform.instance.prepare method that implement same functionality as warmup on Android for all platforms, in addition to be able to take PrepareOptions as a parameter and return PrepareResults that would include MapCapabilities object holding isAdvancedMarkersAvailable boolean flag.

Something like this:

Future<PrepareResult> prepare([PrepareOptions? options]);

@immutable
class PrepareOptions {
 const PrepareOptions({this.mapId});
 
 /// Cloud map ID to check capabilities for.
 final String? mapId;
}

@immutable
class PrepareResult {
 const PrepareResult({
   required this.capabilities,
 });
 
 final MapCapabilities capabilities;
}

@immutable
class MapCapabilities {
 const MapCapabilities({
   required this.advancedMarkersAvailable,
 });
 
 final bool advancedMarkersAvailable;
}

This would allow developers to query the MapCapabilities before MapWidgets.
As this would be part of the platform interface, I think having this extendable like this would be best option for future needs. This could also internally initialize the renderer for Android, but I think keeping it as android specific method is still fine; as devs can still separately use that to check the renderer type on Android.

Not sure how performant this prepare functionality would be on each platform without testing this approach first, but in most cases developers can do this early on app initialization before map views are most likely even needed to be shown yet.

MapCapabilities could be extended later with following options if seen imporant: Android, iOS. On Android there is also following listener available OnMapCapabilitiesChangedListener, which existence tells that the capabilities could change dynamically, but it is not documented, on what situation this could happen. This could potentially mess up things as well.

Implementing this prepare would need similar MapsInitializerApi to be implemented for iOS as it is already done for Android.

After this is landed, the old GoogleMapsFlutterPlatform.instance.isAdvancedMarkersAvailable and most likely GoogleMapsFlutterAndroid.instance.warmup could both be deprecated.

If this approach sounds good to you, I could implement this in quite short notice.

The current implementation creates a really poor developer experience when developers want to use advanced markers (sticking with legacy markers avoids this issue entirely). To use advanced markers, developers need to first initialize the map without markers to be able check its capability to show advanced markers, and then branch their logic based on the response:

  • If advanced markers are supported (true): They can add AdvancedMarkers directly to the map.
  • If advanced markers are not supported (false): They must fall back to the legacy MarkerType, meaning the map needs to be re-created before legacy markers can be used.

In both cases, this required roundtrip prevents developers from adding markers during map initialization, which will likely cause a visible lag before markers appear on the screen.

Also, if a proper GMP MapID is given to the MapWidget and billing is set up properly for the Google Cloud project, then mapCapabilities should return true for isAdvancedMarkersAvailable; however, it is not clearly documented in which situations the value can be false. So, I am not sure how safe it is to assume that isAdvancedMarkersAvailable will always return a true value, even when the mapId and billing are set up correctly. For example, it might be that advanced markers are not supported on the legacy Android renderer.

Sorry for late response.

This PR LGTM

@stuartmorgan-g
Copy link
Collaborator Author

Good rule of thumb, apps shouldn't be importing the platform interface if they are only using the primary plugin?

Yes. Having platform interface imports in app-facing package examples is usually a red flag (although things like the renderer selection are a legitimate use case for that), and I really should have caught that in the initial review.

@stuartmorgan-g
Copy link
Collaborator Author

We could implement new GoogleMapsFlutterPlatform.instance.prepare method that implement same functionality as warmup on Android for all platforms, in addition to be able to take PrepareOptions as a parameter and return PrepareResults that would include MapCapabilities object holding isAdvancedMarkersAvailable boolean flag.

It's not clear to me how that would work; looking at the native implementations of the current queries, they are calling methods on a specific maps instance, not a global call like Android warmup.

I've filed flutter/flutter#183892 to continue discussion/investigation of this; I think the next step would be a short design document about how the flow of querying for support and then enabling should work. It seems like if the query is something we can only map on a maps instance, we may need to make enabling it something that happens post-initialization, although as you point out that means the map can't have initial markers. I think this needs more exploration in a doc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants