Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c35a2c2

Browse files
stuartmorgan-gAdam Harwood
authored and
Adam Harwood
committed
[google_maps_flutter] Default Android to Hybrid Composition (flutter#6334)
1 parent e59248d commit c35a2c2

File tree

9 files changed

+138
-23
lines changed

9 files changed

+138
-23
lines changed

packages/google_maps_flutter/google_maps_flutter_android/CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
## NEXT
1+
## 2.3.0
22

3+
* Switches the default for `useAndroidViewSurface` to true, and adds
4+
information about the current mode behaviors to the README.
35
* Updates minimum Flutter version to 2.10.
46

57
## 2.2.0

packages/google_maps_flutter/google_maps_flutter_android/README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# google\_maps\_flutter\_android
22

3+
<?code-excerpt path-base="excerpts/packages/google_maps_flutter_example"?>
4+
35
The Android implementation of [`google_maps_flutter`][1].
46

57
## Usage
@@ -8,5 +10,45 @@ This package is [endorsed][2], which means you can simply use
810
`google_maps_flutter` normally. This package will be automatically included in
911
your app when you do.
1012

13+
## Display Mode
14+
15+
This plugin supports two different [platform view display modes][3]. The default
16+
display mode is subject to change in the future, and will not be considered a
17+
breaking change, so if you want to ensure a specific mode you can set it
18+
explicitly:
19+
20+
<?code-excerpt "readme_excerpts.dart (DisplayMode)"?>
21+
```dart
22+
import 'package:google_maps_flutter_android/google_maps_flutter_android.dart';
23+
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
24+
25+
void main() {
26+
// Require Hybrid Composition mode on Android.
27+
final GoogleMapsFlutterPlatform mapsImplementation =
28+
GoogleMapsFlutterPlatform.instance;
29+
if (mapsImplementation is GoogleMapsFlutterAndroid) {
30+
mapsImplementation.useAndroidViewSurface = true;
31+
}
32+
// ···
33+
}
34+
```
35+
36+
### Hybrid Composition
37+
38+
This is the current default mode, and corresponds to
39+
`useAndroidViewSurface = true`. It ensures that the map display will work as
40+
expected, at the cost of some performance.
41+
42+
### Texture Layer Hybrid Composition
43+
44+
This is a new display mode used by most plugins starting with Flutter 3.0, and
45+
corresponds to `useAndroidViewSurface = false`. This is more performant than
46+
Hybrid Composition, but currently [misses certain map updates][4].
47+
48+
This mode will likely become the default in future versions if/when the
49+
missed updates issue can be resolved.
50+
1151
[1]: https://pub.dev/packages/google_maps_flutter
1252
[2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin
53+
[3]: https://docs.flutter.dev/development/platform-integration/android/platform-views
54+
[4]: https://github.com/flutter/flutter/issues/103686
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
targets:
2+
$default:
3+
sources:
4+
include:
5+
- lib/**
6+
# Some default includes that aren't really used here but will prevent
7+
# false-negative warnings:
8+
- $package$
9+
- lib/$lib$
10+
exclude:
11+
- '**/.*/**'
12+
- '**/build/**'
13+
builders:
14+
code_excerpter|code_excerpter:
15+
enabled: true

packages/google_maps_flutter/google_maps_flutter_android/example/integration_test/google_maps_test.dart

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,28 @@ void main() {
2323
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
2424
GoogleMapsFlutterPlatform.instance.enableDebugInspection();
2525

26+
// Repeatedly checks an asynchronous value against a test condition, waiting
27+
// on frame between each check, returing the value if it passes the predicate
28+
// before [maxTries] is reached.
29+
//
30+
// Returns null if the predicate is never satisfied.
31+
//
32+
// This is useful for cases where the Maps SDK has some internally
33+
// asynchronous operation that we don't have visibility into (e.g., native UI
34+
// animations).
35+
Future<T?> waitForValueMatchingPredicate<T>(WidgetTester tester,
36+
Future<T> Function() getValue, bool Function(T) predicate,
37+
{int maxTries = 100}) async {
38+
for (int i = 0; i < maxTries; i++) {
39+
final T value = await getValue();
40+
if (predicate(value)) {
41+
return value;
42+
}
43+
await tester.pump();
44+
}
45+
return null;
46+
}
47+
2648
testWidgets('uses surface view', (WidgetTester tester) async {
2749
final GoogleMapsFlutterAndroid instance =
2850
GoogleMapsFlutterPlatform.instance as GoogleMapsFlutterAndroid;
@@ -484,12 +506,13 @@ void main() {
484506
final ExampleGoogleMapController mapController =
485507
await mapControllerCompleter.future;
486508

509+
// Wait for the visible region to be non-zero.
487510
final LatLngBounds firstVisibleRegion =
488-
await mapController.getVisibleRegion();
489-
490-
expect(firstVisibleRegion, isNotNull);
491-
expect(firstVisibleRegion.southwest, isNotNull);
492-
expect(firstVisibleRegion.northeast, isNotNull);
511+
await waitForValueMatchingPredicate<LatLngBounds>(
512+
tester,
513+
() => mapController.getVisibleRegion(),
514+
(LatLngBounds bounds) => bounds != zeroLatLngBounds) ??
515+
zeroLatLngBounds;
493516
expect(firstVisibleRegion, isNot(zeroLatLngBounds));
494517
expect(firstVisibleRegion.contains(_kInitialMapCenter), isTrue);
495518

@@ -520,9 +543,6 @@ void main() {
520543
final LatLngBounds secondVisibleRegion =
521544
await mapController.getVisibleRegion();
522545

523-
expect(secondVisibleRegion, isNotNull);
524-
expect(secondVisibleRegion.southwest, isNotNull);
525-
expect(secondVisibleRegion.northeast, isNotNull);
526546
expect(secondVisibleRegion, isNot(zeroLatLngBounds));
527547

528548
expect(firstVisibleRegion, isNot(secondVisibleRegion));
@@ -922,7 +942,13 @@ void main() {
922942
expect(iwVisibleStatus, false);
923943

924944
await controller.showMarkerInfoWindow(marker.markerId);
925-
iwVisibleStatus = await controller.isMarkerInfoWindowShown(marker.markerId);
945+
// The Maps SDK doesn't always return true for whether it is shown
946+
// immediately after showing it, so wait for it to report as shown.
947+
iwVisibleStatus = await waitForValueMatchingPredicate<bool>(
948+
tester,
949+
() => controller.isMarkerInfoWindowShown(marker.markerId),
950+
(bool visible) => visible) ??
951+
false;
926952
expect(iwVisibleStatus, true);
927953

928954
await controller.hideMarkerInfoWindow(marker.markerId);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter/material.dart';
6+
// #docregion DisplayMode
7+
import 'package:google_maps_flutter_android/google_maps_flutter_android.dart';
8+
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
9+
10+
void main() {
11+
// Require Hybrid Composition mode on Android.
12+
final GoogleMapsFlutterPlatform mapsImplementation =
13+
GoogleMapsFlutterPlatform.instance;
14+
if (mapsImplementation is GoogleMapsFlutterAndroid) {
15+
mapsImplementation.useAndroidViewSurface = true;
16+
}
17+
// #enddocregion DisplayMode
18+
runApp(const MaterialApp());
19+
// #docregion DisplayMode
20+
}
21+
// #enddocregion DisplayMode

packages/google_maps_flutter/google_maps_flutter_android/example/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ dependencies:
2121
google_maps_flutter_platform_interface: ^2.2.1
2222

2323
dev_dependencies:
24+
build_runner: ^2.1.10
2425
espresso: ^0.1.0+2
2526
flutter_driver:
2627
sdk: flutter

packages/google_maps_flutter/google_maps_flutter_android/lib/src/google_maps_flutter_android.dart

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -471,19 +471,14 @@ class GoogleMapsFlutterAndroid extends GoogleMapsFlutterPlatform {
471471
return _channel(mapId).invokeMethod<Uint8List>('map#takeSnapshot');
472472
}
473473

474-
/// Set [GoogleMapsFlutterPlatform] to use [AndroidViewSurface] to build the Google Maps widget.
474+
/// Set [GoogleMapsFlutterPlatform] to use [AndroidViewSurface] to build the
475+
/// Google Maps widget.
475476
///
476-
/// This implementation uses hybrid composition to render the Google Maps
477-
/// Widget on Android. This comes at the cost of some performance on Android
478-
/// versions below 10. See
479-
/// https://flutter.dev/docs/development/platform-integration/platform-views#performance for more
480-
/// information.
477+
/// See https://pub.dev/packages/google_maps_flutter_android#display-mode
478+
/// for more information.
481479
///
482-
/// If set to true, the google map widget should be built with
483-
/// [buildViewWithTextDirection] instead of [buildView].
484-
///
485-
/// Defaults to false.
486-
bool useAndroidViewSurface = false;
480+
/// Currently defaults to true, but the default is subject to change.
481+
bool useAndroidViewSurface = true;
487482

488483
Widget _buildView(
489484
int creationId,

packages/google_maps_flutter/google_maps_flutter_android/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: google_maps_flutter_android
22
description: Android implementation of the google_maps_flutter plugin.
33
repository: https://github.com/flutter/plugins/tree/main/packages/google_maps_flutter/google_maps_flutter_android
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22
5-
version: 2.2.0
5+
version: 2.3.0
66

77
environment:
88
sdk: ">=2.14.0 <3.0.0"

packages/google_maps_flutter/google_maps_flutter_android/test/google_maps_flutter_android_test.dart

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,10 @@ void main() {
124124
});
125125

126126
test(
127-
'Default widget is AndroidView',
127+
'Does not use PlatformViewLink when using TLHC',
128128
() async {
129129
final GoogleMapsFlutterAndroid maps = GoogleMapsFlutterAndroid();
130+
maps.useAndroidViewSurface = false;
130131
final Widget widget = maps.buildViewWithConfiguration(1, (int _) {},
131132
widgetConfiguration: const MapWidgetConfiguration(
132133
initialCameraPosition:
@@ -150,4 +151,16 @@ void main() {
150151

151152
expect(widget, isA<PlatformViewLink>());
152153
});
154+
155+
testWidgets('Defaults to surface view', (WidgetTester tester) async {
156+
final GoogleMapsFlutterAndroid maps = GoogleMapsFlutterAndroid();
157+
158+
final Widget widget = maps.buildViewWithConfiguration(1, (int _) {},
159+
widgetConfiguration: const MapWidgetConfiguration(
160+
initialCameraPosition:
161+
CameraPosition(target: LatLng(0, 0), zoom: 1),
162+
textDirection: TextDirection.ltr));
163+
164+
expect(widget, isA<PlatformViewLink>());
165+
});
153166
}

0 commit comments

Comments
 (0)