Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Support Hybrid Composition through the GoogleMaps Widget #4082

Merged
merged 17 commits into from Oct 28, 2021

Conversation

bparrishMines
Copy link
Contributor

@bparrishMines bparrishMines commented Jun 23, 2021

Since the changes in #4017 avoids a breaking change, a new buildView method needed to be added. This switches the GoogleMaps widget to use this new platform specific method.

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the relevant style guides and ran the auto-formatter. (Note that unlike the flutter/flutter repo, the flutter/plugins repo does use dart format.)
  • I signed the CLA.
  • The title of the PR starts with the name of the plugin surrounded by square brackets, e.g. [shared_preferences]
  • I listed at least one issue that this PR fixes in the description above.
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy.
  • I updated CHANGELOG.md to add a description of the change.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test exempt.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@google-cla google-cla bot added the cla: yes label Jun 23, 2021
@bparrishMines bparrishMines changed the title Android maps Support Hybrid Composition through the GoogleMaps Widget Jun 23, 2021
@@ -46,6 +46,19 @@ This means that app will only be available for users that run Android SDK 20 or
android:value="YOUR KEY HERE"/>
```

#### Hybrid Composition

To use Hybrid Composition to render the `GoogleMap` widget on Android. Set the
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: s/. Set the/, set/

@@ -46,6 +46,19 @@ This means that app will only be available for users that run Android SDK 20 or
android:value="YOUR KEY HERE"/>
```

#### Hybrid Composition

To use Hybrid Composition to render the `GoogleMap` widget on Android. Set the
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: maybe link "Hybrid Composition" to an explanation of what that is for people who don't know?

@@ -66,5 +68,11 @@ class MapsDemo extends StatelessWidget {
}

void main() {
WidgetsFlutterBinding.ensureInitialized();
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this necessary? Setting that flag doesn't send a message, does it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right. Force of habit. removed

return GoogleMapsFlutterPlatform.instance.buildView(
final GoogleMapsFlutterPlatform platform =
GoogleMapsFlutterPlatform.instance;
if (platform is MethodChannelGoogleMapsFlutter) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why can't the new method be called unconditionally? The delegation to the old method was supposed to be handled by a default implementation in the platform interface.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The default implementation (MethodChannelGoogleMapsFlutter) does call the old method if the platform is not android or hybrid composition is turned off. However, web switches to another platform instance: https://github.com/flutter/plugins/blob/master/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_flutter_web.dart#L13.

So in this case, we would need to call the other method, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, that was poorly phrased; by "default implementation" I mean the code that's part of the base class that all implementations extend from. Having a fallback implementation there is what makes this overall change harmless even for federated implementations we don't even know about.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah ok. So buildViewWithTextDirection was only added to MethodChannelGoogleMapsFlutter and not to GoogleMapsFlutterPlatform. This is same for the flag useAndroidViewSurface. This was done because this was an Android only requirement.

Were you thinking that buildViewWithTextDirection should have been added to GoogleMapsFlutterPlatform as well? I think that makes more sense and could be done without a breaking change.

Copy link
Contributor

Choose a reason for hiding this comment

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

That was what I had intended in the discussion, yes. However, IIRC there was discussion of this being temporary, in which case I'm okay with this approach if you don't want to go back and make another change to the platform interface given that it's already been done. (If this were permanent, it would be more important that we not embed implementation-specific code here as much as possible.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For this method to only be temporary, the platform_interface would have to be broken and bumped to version 3.0. This is because any implementation would need to add the additional parameter to their method. However, I believe the policy is to avoid breaking changes to the platform_interface.

An alternative is to have two methods, and to call buildViewWithTextDirection by default in google_maps_flutter. But this would still break any implementation that doesn't implement buildViewWithTextDirection as the method would throw an UnimplementedError().

This PR essentially makes buildViewWithTextDirection unique to MethodChannelPlatform. The GoogleMap widget then calls it iff it is MethodChannelPlatform. I believe this avoids any breaking changes and any of the implementations would still work with the plugin.

Copy link
Contributor

Choose a reason for hiding this comment

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

An alternative is to have two methods, and to call buildViewWithTextDirection by default in google_maps_flutter. But this would still break any implementation that doesn't implement buildViewWithTextDirection as the method would throw an UnimplementedError().

That's why I had recommended having the method not throw UnimplementedError, but instead calling the old method.

But my question wasn't about implemented, but the ideal goal: do we want this new parameter forever, or is the need for this parameter temporary? I had thought it was the latter, but again, I may have misunderstood.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, you wanted that done at the interface level and not the implementation level. That makes since.

This parameter is required for Android hybrid composition unless we don't want the user to be able to change the text direction. I haven't seen a way around it yet that doesn't involve framework changes. My intention is that it's a permanent parameter.

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, sorry for the confusion on my part about the intended lifespan. In that case yes, I think we should update the platform interface to have a default implementation that calls the old method with a default value. Then implementations (those that want a different behavior than that default) can override both, but nobody will be broken and the details of who implements what won't bleed into this package.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That works for me! I updated #4121 to reflect this.

_mapId,
onPlatformViewCreated,
textDirection: widget.textDirection ??
Directionality.maybeOf(context) ??
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This may return null if there is no Directionality ancestor. This was the case with one of the tests, so I also added a default TextDirection.ltr.

@bparrishMines
Copy link
Contributor Author

@stuartmorgan I believe this is ready for another review.

Copy link
Contributor

@stuartmorgan stuartmorgan left a comment

Choose a reason for hiding this comment

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

Sorry for the delay, just a couple of small things.

@stuartmorgan
Copy link
Contributor

Was this ready for me to review again?

@bparrishMines
Copy link
Contributor Author

Was this ready for me to review again?

@stuartmorgan I forgot that this hadn't landed yet. But, yes it's ready for another review.

Copy link
Contributor

@stuartmorgan stuartmorgan left a comment

Choose a reason for hiding this comment

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

LGTM other than a nit about assertions.

@@ -38,6 +38,48 @@ class UnknownMapObjectIdError extends Error {
}
}

/// Android specific settings for [GoogleMap].
class AndroidGoogleMapsFlutter {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would expect this to be a MethodChannelGoogleMapsFlutter subclass. I guess we can add that later without it being a breaking change though, and doing it now would have registration complexities since we don't have dartPluginClass support for mobile on stable yet.

GoogleMapsFlutterPlatform.instance is MethodChannelGoogleMapsFlutter,
'This feature is only supported when `GoogleMapsFlutterPlatform.instance` '
'is a `MethodChannelGoogleMapsFlutter`; The default implementation for Android.',
);
Copy link
Contributor

Choose a reason for hiding this comment

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

This will interfere with people setting mock platform implementations for tests, which is the recommended way of mocking federated plugins. We should no-op it (returning false) rather than asserting.

GoogleMapsFlutterPlatform.instance is MethodChannelGoogleMapsFlutter,
'This feature is only supported when `GoogleMapsFlutterPlatform.instance` '
'is a `MethodChannelGoogleMapsFlutter`; The default implementation for Android.',
);
Copy link
Contributor

Choose a reason for hiding this comment

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

Same.

@bparrishMines bparrishMines merged commit 34ea0c3 into flutter:master Oct 28, 2021
@bparrishMines bparrishMines deleted the android_maps branch October 28, 2021 17:54
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 28, 2021
NickalasB added a commit to NickalasB/plugins that referenced this pull request Nov 4, 2021
* master:
  [webview_flutter] Deprecate evaluateJavascript in favour of runJavaScript and runJavaScriptForResult. (flutter#4403)
  [webview_flutter] Add interface methods to load local files and HTML strings. (flutter#4446)
  [ci] add pedantic dep to new in_app_purchase pkgs (flutter#4471)
  [ci] Remove unused dep from file_selector. (flutter#4468)
  [ci] update build_runner dep in android_intent and file_selector example (flutter#4467)
  [webview_flutter] Add platform interface method `loadRequest`. (flutter#4450)
  Remove -Werror from deprecated plugin Android builds (flutter#4466)
  [webview_flutter] Update webview packages for Android and iOS to implement `runJavascript` and `runJavascriptReturningResult`. (flutter#4402)
  [camera] Fix CamcorderProfile Usages (flutter#4423)
  [google_sign_in] Use a transparent image as a placeholder for the `GoogleUserCircleAvatar` (flutter#4391)
  [in_app_purchase]IAP/platform interface add cancel status (flutter#4093)
  [image_picker] doc:readme image picker misprints (flutter#4421)
  Support Hybrid Composition through the GoogleMaps Widget (flutter#4082)
  [path_provider] started supporting background platform channels (flutter#4443)
  [device_info] started using Background Platform Channels (flutter#4456)

# Conflicts:
#	packages/webview_flutter/webview_flutter/CHANGELOG.md
#	packages/webview_flutter/webview_flutter/pubspec.yaml
amantoux pushed a commit to amantoux/plugins that referenced this pull request Dec 11, 2021
KyleFin pushed a commit to KyleFin/plugins that referenced this pull request Dec 21, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
2 participants