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

Commit 15cfe8a

Browse files
[webview_flutter_android] Adds support for selecting Hybrid Composition (#6864)
* add displayWithHybridComposition flag * move duplicate method * unit tests * adds * update docs * create platformviewsserviceproxy * use proxy for platformviewsservice * remove usused code * update display mode * use clever imports
1 parent c61ac23 commit 15cfe8a

File tree

8 files changed

+1110
-364
lines changed

8 files changed

+1110
-364
lines changed

packages/webview_flutter/webview_flutter_android/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 3.1.0
2+
3+
* Adds support for selecting Hybrid Composition on versions 23+. Please use
4+
`AndroidWebViewControllerCreationParams.displayWithHybridComposition`.
5+
16
## 3.0.0
27

38
* **BREAKING CHANGE** Updates platform implementation to `2.0.0` release of

packages/webview_flutter/webview_flutter_android/README.md

+25
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,31 @@ The Android implementation of [`webview_flutter`][1].
77
This package is [endorsed][2], which means you can simply use `webview_flutter`
88
normally. This package will be automatically included in your app when you do.
99

10+
## Display Mode
11+
12+
This plugin supports two different platform view display modes. The default display mode is subject
13+
to change in the future, and will not be considered a breaking change, so if you want to ensure a
14+
specific mode, you can set it explicitly.
15+
16+
### Texture Layer Hybrid Composition
17+
18+
This is the current default mode for versions >=23. This is a new display mode used by most
19+
plugins starting with Flutter 3.0. This is more performant than Hybrid Composition, but has some
20+
limitations from using an Android [SurfaceTexture](https://developer.android.com/reference/android/graphics/SurfaceTexture).
21+
See:
22+
* https://github.com/flutter/flutter/issues/104889
23+
* https://github.com/flutter/flutter/issues/116954
24+
25+
### Hybrid Composition
26+
27+
This is the current default mode for versions <23. It ensures that the WebView will display and work
28+
as expected, at the cost of some performance. See:
29+
* https://flutter.dev/docs/development/platform-integration/platform-views#performance
30+
31+
This can be configured for versions >=23 with
32+
`AndroidWebViewWidgetCreationParams.displayWithHybridComposition`. See https://pub.dev/packages/webview_flutter#platform-specific-features
33+
for more details on setting platform-specific features in the main plugin.
34+
1035
## Contributing
1136

1237
This package uses [pigeon][3] to generate the communication layer between Flutter and the host

packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import 'dart:io';
1313
// ignore: unnecessary_import
1414
import 'dart:typed_data';
1515

16-
import 'package:flutter/foundation.dart';
1716
import 'package:flutter/material.dart';
1817
import 'package:flutter/services.dart';
1918
import 'package:flutter_test/flutter_test.dart';

packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart

+75-25
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import 'android_proxy.dart';
1616
import 'android_webview.dart' as android_webview;
1717
import 'android_webview.dart';
1818
import 'instance_manager.dart';
19+
import 'platform_views_service_proxy.dart';
1920
import 'weak_reference_utils.dart';
2021

2122
/// Object specifying creation parameters for creating a [AndroidWebViewController].
@@ -369,20 +370,28 @@ class AndroidWebViewWidgetCreationParams
369370
required super.controller,
370371
super.layoutDirection,
371372
super.gestureRecognizers,
373+
this.displayWithHybridComposition = false,
372374
@visibleForTesting InstanceManager? instanceManager,
375+
@visibleForTesting
376+
this.platformViewsServiceProxy = const PlatformViewsServiceProxy(),
373377
}) : instanceManager = instanceManager ?? JavaObject.globalInstanceManager;
374378

375379
/// Constructs a [WebKitWebViewWidgetCreationParams] using a
376380
/// [PlatformWebViewWidgetCreationParams].
377381
AndroidWebViewWidgetCreationParams.fromPlatformWebViewWidgetCreationParams(
378382
PlatformWebViewWidgetCreationParams params, {
379-
InstanceManager? instanceManager,
383+
bool displayWithHybridComposition = false,
384+
@visibleForTesting InstanceManager? instanceManager,
385+
@visibleForTesting PlatformViewsServiceProxy platformViewsServiceProxy =
386+
const PlatformViewsServiceProxy(),
380387
}) : this(
381388
key: params.key,
382389
controller: params.controller,
383390
layoutDirection: params.layoutDirection,
384391
gestureRecognizers: params.gestureRecognizers,
392+
displayWithHybridComposition: displayWithHybridComposition,
385393
instanceManager: instanceManager,
394+
platformViewsServiceProxy: platformViewsServiceProxy,
386395
);
387396

388397
/// Maintains instances used to communicate with the native objects they
@@ -392,6 +401,25 @@ class AndroidWebViewWidgetCreationParams
392401
/// outside of tests.
393402
@visibleForTesting
394403
final InstanceManager instanceManager;
404+
405+
/// Proxy that provides access to the platform views service.
406+
///
407+
/// This service allows creating and controlling platform-specific views.
408+
@visibleForTesting
409+
final PlatformViewsServiceProxy platformViewsServiceProxy;
410+
411+
/// Whether the [WebView] will be displayed using the Hybrid Composition
412+
/// PlatformView implementation.
413+
///
414+
/// For most use cases, this flag should be set to false. Hybrid Composition
415+
/// can have performance costs but doesn't have the limitation of rendering to
416+
/// an Android SurfaceTexture. See
417+
/// * https://flutter.dev/docs/development/platform-integration/platform-views#performance
418+
/// * https://github.com/flutter/flutter/issues/104889
419+
/// * https://github.com/flutter/flutter/issues/116954
420+
///
421+
/// Defaults to false.
422+
final bool displayWithHybridComposition;
395423
}
396424

397425
/// An implementation of [PlatformWebViewWidget] with the Android WebView API.
@@ -411,30 +439,52 @@ class AndroidWebViewWidget extends PlatformWebViewWidget {
411439
@override
412440
Widget build(BuildContext context) {
413441
return PlatformViewLink(
414-
key: _androidParams.key,
442+
key: _androidParams.key,
443+
viewType: 'plugins.flutter.io/webview',
444+
surfaceFactory: (
445+
BuildContext context,
446+
PlatformViewController controller,
447+
) {
448+
return AndroidViewSurface(
449+
controller: controller as AndroidViewController,
450+
gestureRecognizers: _androidParams.gestureRecognizers,
451+
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
452+
);
453+
},
454+
onCreatePlatformView: (PlatformViewCreationParams params) {
455+
return _initAndroidView(
456+
params,
457+
displayWithHybridComposition:
458+
_androidParams.displayWithHybridComposition,
459+
)
460+
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
461+
..create();
462+
},
463+
);
464+
}
465+
466+
AndroidViewController _initAndroidView(
467+
PlatformViewCreationParams params, {
468+
required bool displayWithHybridComposition,
469+
}) {
470+
if (displayWithHybridComposition) {
471+
return _androidParams.platformViewsServiceProxy.initExpensiveAndroidView(
472+
id: params.id,
415473
viewType: 'plugins.flutter.io/webview',
416-
surfaceFactory: (
417-
BuildContext context,
418-
PlatformViewController controller,
419-
) {
420-
return AndroidViewSurface(
421-
controller: controller as AndroidViewController,
422-
gestureRecognizers: _androidParams.gestureRecognizers,
423-
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
424-
);
425-
},
426-
onCreatePlatformView: (PlatformViewCreationParams params) {
427-
return PlatformViewsService.initSurfaceAndroidView(
428-
id: params.id,
429-
viewType: 'plugins.flutter.io/webview',
430-
layoutDirection: _androidParams.layoutDirection,
431-
creationParams: _androidParams.instanceManager.getIdentifier(
432-
(_androidParams.controller as AndroidWebViewController)
433-
._webView),
434-
creationParamsCodec: const StandardMessageCodec(),
435-
)
436-
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
437-
..create();
438-
});
474+
layoutDirection: _androidParams.layoutDirection,
475+
creationParams: _androidParams.instanceManager.getIdentifier(
476+
(_androidParams.controller as AndroidWebViewController)._webView),
477+
creationParamsCodec: const StandardMessageCodec(),
478+
);
479+
} else {
480+
return _androidParams.platformViewsServiceProxy.initSurfaceAndroidView(
481+
id: params.id,
482+
viewType: 'plugins.flutter.io/webview',
483+
layoutDirection: _androidParams.layoutDirection,
484+
creationParams: _androidParams.instanceManager.getIdentifier(
485+
(_androidParams.controller as AndroidWebViewController)._webView),
486+
creationParamsCodec: const StandardMessageCodec(),
487+
);
488+
}
439489
}
440490
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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+
import 'package:flutter/services.dart';
7+
8+
/// Proxy that provides access to the platform views service.
9+
///
10+
/// This service allows creating and controlling platform-specific views.
11+
@immutable
12+
class PlatformViewsServiceProxy {
13+
/// Constructs a [PlatformViewsServiceProxy].
14+
const PlatformViewsServiceProxy();
15+
16+
/// Proxy method for [PlatformViewsService.initExpensiveAndroidView].
17+
ExpensiveAndroidViewController initExpensiveAndroidView({
18+
required int id,
19+
required String viewType,
20+
required TextDirection layoutDirection,
21+
dynamic creationParams,
22+
MessageCodec<dynamic>? creationParamsCodec,
23+
VoidCallback? onFocus,
24+
}) {
25+
return PlatformViewsService.initExpensiveAndroidView(
26+
id: id,
27+
viewType: viewType,
28+
layoutDirection: layoutDirection,
29+
creationParams: creationParams,
30+
creationParamsCodec: creationParamsCodec,
31+
onFocus: onFocus,
32+
);
33+
}
34+
35+
/// Proxy method for [PlatformViewsService.initSurfaceAndroidView].
36+
SurfaceAndroidViewController initSurfaceAndroidView({
37+
required int id,
38+
required String viewType,
39+
required TextDirection layoutDirection,
40+
dynamic creationParams,
41+
MessageCodec<dynamic>? creationParamsCodec,
42+
VoidCallback? onFocus,
43+
}) {
44+
return PlatformViewsService.initSurfaceAndroidView(
45+
id: id,
46+
viewType: viewType,
47+
layoutDirection: layoutDirection,
48+
creationParams: creationParams,
49+
creationParamsCodec: creationParamsCodec,
50+
onFocus: onFocus,
51+
);
52+
}
53+
}

packages/webview_flutter/webview_flutter_android/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: webview_flutter_android
22
description: A Flutter plugin that provides a WebView widget on Android.
33
repository: https://github.com/flutter/plugins/tree/main/packages/webview_flutter/webview_flutter_android
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
5-
version: 3.0.0
5+
version: 3.1.0
66

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

0 commit comments

Comments
 (0)