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

Commit

Permalink
[webview_flutter_android] Adds support for selecting Hybrid Compositi…
Browse files Browse the repository at this point in the history
…on (#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
  • Loading branch information
bparrishMines committed Dec 21, 2022
1 parent c61ac23 commit 15cfe8a
Show file tree
Hide file tree
Showing 8 changed files with 1,110 additions and 364 deletions.
5 changes: 5 additions & 0 deletions packages/webview_flutter/webview_flutter_android/CHANGELOG.md
@@ -1,3 +1,8 @@
## 3.1.0

* Adds support for selecting Hybrid Composition on versions 23+. Please use
`AndroidWebViewControllerCreationParams.displayWithHybridComposition`.

## 3.0.0

* **BREAKING CHANGE** Updates platform implementation to `2.0.0` release of
Expand Down
25 changes: 25 additions & 0 deletions packages/webview_flutter/webview_flutter_android/README.md
Expand Up @@ -7,6 +7,31 @@ The Android implementation of [`webview_flutter`][1].
This package is [endorsed][2], which means you can simply use `webview_flutter`
normally. This package will be automatically included in your app when you do.

## Display Mode

This plugin supports two different platform view display modes. The default display mode is subject
to change in the future, and will not be considered a breaking change, so if you want to ensure a
specific mode, you can set it explicitly.

### Texture Layer Hybrid Composition

This is the current default mode for versions >=23. This is a new display mode used by most
plugins starting with Flutter 3.0. This is more performant than Hybrid Composition, but has some
limitations from using an Android [SurfaceTexture](https://developer.android.com/reference/android/graphics/SurfaceTexture).
See:
* https://github.com/flutter/flutter/issues/104889
* https://github.com/flutter/flutter/issues/116954

### Hybrid Composition

This is the current default mode for versions <23. It ensures that the WebView will display and work
as expected, at the cost of some performance. See:
* https://flutter.dev/docs/development/platform-integration/platform-views#performance

This can be configured for versions >=23 with
`AndroidWebViewWidgetCreationParams.displayWithHybridComposition`. See https://pub.dev/packages/webview_flutter#platform-specific-features
for more details on setting platform-specific features in the main plugin.

## Contributing

This package uses [pigeon][3] to generate the communication layer between Flutter and the host
Expand Down
Expand Up @@ -13,7 +13,6 @@ import 'dart:io';
// ignore: unnecessary_import
import 'dart:typed_data';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
Expand Down
Expand Up @@ -16,6 +16,7 @@ import 'android_proxy.dart';
import 'android_webview.dart' as android_webview;
import 'android_webview.dart';
import 'instance_manager.dart';
import 'platform_views_service_proxy.dart';
import 'weak_reference_utils.dart';

/// Object specifying creation parameters for creating a [AndroidWebViewController].
Expand Down Expand Up @@ -369,20 +370,28 @@ class AndroidWebViewWidgetCreationParams
required super.controller,
super.layoutDirection,
super.gestureRecognizers,
this.displayWithHybridComposition = false,
@visibleForTesting InstanceManager? instanceManager,
@visibleForTesting
this.platformViewsServiceProxy = const PlatformViewsServiceProxy(),
}) : instanceManager = instanceManager ?? JavaObject.globalInstanceManager;

/// Constructs a [WebKitWebViewWidgetCreationParams] using a
/// [PlatformWebViewWidgetCreationParams].
AndroidWebViewWidgetCreationParams.fromPlatformWebViewWidgetCreationParams(
PlatformWebViewWidgetCreationParams params, {
InstanceManager? instanceManager,
bool displayWithHybridComposition = false,
@visibleForTesting InstanceManager? instanceManager,
@visibleForTesting PlatformViewsServiceProxy platformViewsServiceProxy =
const PlatformViewsServiceProxy(),
}) : this(
key: params.key,
controller: params.controller,
layoutDirection: params.layoutDirection,
gestureRecognizers: params.gestureRecognizers,
displayWithHybridComposition: displayWithHybridComposition,
instanceManager: instanceManager,
platformViewsServiceProxy: platformViewsServiceProxy,
);

/// Maintains instances used to communicate with the native objects they
Expand All @@ -392,6 +401,25 @@ class AndroidWebViewWidgetCreationParams
/// outside of tests.
@visibleForTesting
final InstanceManager instanceManager;

/// Proxy that provides access to the platform views service.
///
/// This service allows creating and controlling platform-specific views.
@visibleForTesting
final PlatformViewsServiceProxy platformViewsServiceProxy;

/// Whether the [WebView] will be displayed using the Hybrid Composition
/// PlatformView implementation.
///
/// For most use cases, this flag should be set to false. Hybrid Composition
/// can have performance costs but doesn't have the limitation of rendering to
/// an Android SurfaceTexture. See
/// * https://flutter.dev/docs/development/platform-integration/platform-views#performance
/// * https://github.com/flutter/flutter/issues/104889
/// * https://github.com/flutter/flutter/issues/116954
///
/// Defaults to false.
final bool displayWithHybridComposition;
}

/// An implementation of [PlatformWebViewWidget] with the Android WebView API.
Expand All @@ -411,30 +439,52 @@ class AndroidWebViewWidget extends PlatformWebViewWidget {
@override
Widget build(BuildContext context) {
return PlatformViewLink(
key: _androidParams.key,
key: _androidParams.key,
viewType: 'plugins.flutter.io/webview',
surfaceFactory: (
BuildContext context,
PlatformViewController controller,
) {
return AndroidViewSurface(
controller: controller as AndroidViewController,
gestureRecognizers: _androidParams.gestureRecognizers,
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
);
},
onCreatePlatformView: (PlatformViewCreationParams params) {
return _initAndroidView(
params,
displayWithHybridComposition:
_androidParams.displayWithHybridComposition,
)
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
..create();
},
);
}

AndroidViewController _initAndroidView(
PlatformViewCreationParams params, {
required bool displayWithHybridComposition,
}) {
if (displayWithHybridComposition) {
return _androidParams.platformViewsServiceProxy.initExpensiveAndroidView(
id: params.id,
viewType: 'plugins.flutter.io/webview',
surfaceFactory: (
BuildContext context,
PlatformViewController controller,
) {
return AndroidViewSurface(
controller: controller as AndroidViewController,
gestureRecognizers: _androidParams.gestureRecognizers,
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
);
},
onCreatePlatformView: (PlatformViewCreationParams params) {
return PlatformViewsService.initSurfaceAndroidView(
id: params.id,
viewType: 'plugins.flutter.io/webview',
layoutDirection: _androidParams.layoutDirection,
creationParams: _androidParams.instanceManager.getIdentifier(
(_androidParams.controller as AndroidWebViewController)
._webView),
creationParamsCodec: const StandardMessageCodec(),
)
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
..create();
});
layoutDirection: _androidParams.layoutDirection,
creationParams: _androidParams.instanceManager.getIdentifier(
(_androidParams.controller as AndroidWebViewController)._webView),
creationParamsCodec: const StandardMessageCodec(),
);
} else {
return _androidParams.platformViewsServiceProxy.initSurfaceAndroidView(
id: params.id,
viewType: 'plugins.flutter.io/webview',
layoutDirection: _androidParams.layoutDirection,
creationParams: _androidParams.instanceManager.getIdentifier(
(_androidParams.controller as AndroidWebViewController)._webView),
creationParamsCodec: const StandardMessageCodec(),
);
}
}
}
@@ -0,0 +1,53 @@
// 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.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

/// Proxy that provides access to the platform views service.
///
/// This service allows creating and controlling platform-specific views.
@immutable
class PlatformViewsServiceProxy {
/// Constructs a [PlatformViewsServiceProxy].
const PlatformViewsServiceProxy();

/// Proxy method for [PlatformViewsService.initExpensiveAndroidView].
ExpensiveAndroidViewController initExpensiveAndroidView({
required int id,
required String viewType,
required TextDirection layoutDirection,
dynamic creationParams,
MessageCodec<dynamic>? creationParamsCodec,
VoidCallback? onFocus,
}) {
return PlatformViewsService.initExpensiveAndroidView(
id: id,
viewType: viewType,
layoutDirection: layoutDirection,
creationParams: creationParams,
creationParamsCodec: creationParamsCodec,
onFocus: onFocus,
);
}

/// Proxy method for [PlatformViewsService.initSurfaceAndroidView].
SurfaceAndroidViewController initSurfaceAndroidView({
required int id,
required String viewType,
required TextDirection layoutDirection,
dynamic creationParams,
MessageCodec<dynamic>? creationParamsCodec,
VoidCallback? onFocus,
}) {
return PlatformViewsService.initSurfaceAndroidView(
id: id,
viewType: viewType,
layoutDirection: layoutDirection,
creationParams: creationParams,
creationParamsCodec: creationParamsCodec,
onFocus: onFocus,
);
}
}
Expand Up @@ -2,7 +2,7 @@ name: webview_flutter_android
description: A Flutter plugin that provides a WebView widget on Android.
repository: https://github.com/flutter/plugins/tree/main/packages/webview_flutter/webview_flutter_android
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
version: 3.0.0
version: 3.1.0

environment:
sdk: ">=2.17.0 <3.0.0"
Expand Down

0 comments on commit 15cfe8a

Please sign in to comment.