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

[webview_flutter_android] Adds dispose methods for HostApi and FlutterApi of JavaObject #6172

Merged
merged 8 commits into from
Aug 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.9.5

* Adds dispose methods for HostApi and FlutterApi of JavaObject.

## 2.9.4

* Fixes avoid_redundant_argument_values lint warnings and minor typos.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// 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.
// Autogenerated from Pigeon (v3.0.3), do not edit directly.
// Autogenerated from Pigeon (v3.2.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon

package io.flutter.plugins.webviewflutter;
Expand Down Expand Up @@ -271,6 +271,87 @@ public interface Result<T> {
void error(Throwable error);
}

private static class JavaObjectHostApiCodec extends StandardMessageCodec {
public static final JavaObjectHostApiCodec INSTANCE = new JavaObjectHostApiCodec();

private JavaObjectHostApiCodec() {}
}

/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
public interface JavaObjectHostApi {
void dispose(@NonNull Long identifier);

/** The codec used by JavaObjectHostApi. */
static MessageCodec<Object> getCodec() {
return JavaObjectHostApiCodec.INSTANCE;
}

/**
* Sets up an instance of `JavaObjectHostApi` to handle messages through the `binaryMessenger`.
*/
static void setup(BinaryMessenger binaryMessenger, JavaObjectHostApi api) {
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.JavaObjectHostApi.dispose", getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
Map<String, Object> wrapped = new HashMap<>();
try {
ArrayList<Object> args = (ArrayList<Object>) message;
Number identifierArg = (Number) args.get(0);
if (identifierArg == null) {
throw new NullPointerException("identifierArg unexpectedly null.");
}
api.dispose((identifierArg == null) ? null : identifierArg.longValue());
wrapped.put("result", null);
} catch (Error | RuntimeException exception) {
wrapped.put("error", wrapError(exception));
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
}
}

private static class JavaObjectFlutterApiCodec extends StandardMessageCodec {
public static final JavaObjectFlutterApiCodec INSTANCE = new JavaObjectFlutterApiCodec();

private JavaObjectFlutterApiCodec() {}
}

/** Generated class from Pigeon that represents Flutter messages that can be called from Java. */
public static class JavaObjectFlutterApi {
private final BinaryMessenger binaryMessenger;

public JavaObjectFlutterApi(BinaryMessenger argBinaryMessenger) {
this.binaryMessenger = argBinaryMessenger;
}

public interface Reply<T> {
void reply(T reply);
}

static MessageCodec<Object> getCodec() {
return JavaObjectFlutterApiCodec.INSTANCE;
}

public void dispose(@NonNull Long identifierArg, Reply<Void> callback) {
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.JavaObjectFlutterApi.dispose", getCodec());
channel.send(
new ArrayList<Object>(Arrays.asList(identifierArg)),
channelReply -> {
callback.reply(null);
});
}
}

private static class CookieManagerHostApiCodec extends StandardMessageCodec {
public static final CookieManagerHostApiCodec INSTANCE = new CookieManagerHostApiCodec();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 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.

package io.flutter.plugins.webviewflutter;

import androidx.annotation.NonNull;

/**
* A pigeon Host API implementation that handles creating {@link Object}s and invoking its static
* and instance methods.
*
* <p>{@link Object} instances created by {@link JavaObjectHostApiImpl} are used to intercommunicate
* with a paired Dart object.
*/
public class JavaObjectHostApiImpl implements GeneratedAndroidWebView.JavaObjectHostApi {
private final InstanceManager instanceManager;

/**
* Constructs a {@link JavaObjectHostApiImpl}.
*
* @param instanceManager maintains instances stored to communicate with Dart objects
*/
public JavaObjectHostApiImpl(InstanceManager instanceManager) {
this.instanceManager = instanceManager;
}

@Override
public void dispose(@NonNull Long identifier) {
instanceManager.remove(identifier);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 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.

package io.flutter.plugins.webviewflutter;

import static org.junit.Assert.assertNull;

import org.junit.Test;

public class JavaObjectHostApiTest {
@Test
public void dispose() {
final InstanceManager instanceManager = InstanceManager.open(identifier -> {});

final JavaObjectHostApiImpl hostApi = new JavaObjectHostApiImpl(instanceManager);

Object object = new Object();
instanceManager.addDartCreatedInstance(object, 0);

// To free object for garbage collection.
//noinspection UnusedAssignment
object = null;

hostApi.dispose(0L);
Runtime.getRuntime().gc();

assertNull(instanceManager.getInstance(0));

instanceManager.close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'dart:typed_data';
import 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart' show BinaryMessenger;
import 'package:flutter/widgets.dart' show AndroidViewSurface;

import 'android_webview.pigeon.dart';
Expand All @@ -22,17 +23,36 @@ import 'instance_manager.dart';
/// Root of the Java class hierarchy.
///
/// See https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html.
abstract class JavaObject with Copyable {
class JavaObject with Copyable {
/// Constructs a [JavaObject] without creating the associated Java object.
///
/// This should only be used by subclasses created by this library or to
/// create copies.
JavaObject.detached();
JavaObject.detached({
BinaryMessenger? binaryMessenger,
InstanceManager? instanceManager,
}) : _api = JavaObjectHostApiImpl(
binaryMessenger: binaryMessenger,
instanceManager: instanceManager,
);

/// Global instance of [InstanceManager].
static final InstanceManager globalInstanceManager = InstanceManager(
onWeakReferenceRemoved: (_) {},
);

/// Pigeon Host Api implementation for [JavaObject].
final JavaObjectHostApiImpl _api;

/// Release the reference to a native Java instance.
static void dispose(JavaObject instance) {
instance._api.instanceManager.removeWeakReference(instance);
}

@override
JavaObject copy() {
return JavaObject.detached();
}
}

/// An Android View that displays web pages.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// 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.
// Autogenerated from Pigeon (v3.0.3), do not edit directly.
// Autogenerated from Pigeon (v3.2.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name
// @dart = 2.12
Expand Down Expand Up @@ -78,6 +78,78 @@ class WebResourceErrorData {
}
}

class _JavaObjectHostApiCodec extends StandardMessageCodec {
const _JavaObjectHostApiCodec();
}

class JavaObjectHostApi {
/// Constructor for [JavaObjectHostApi]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
JavaObjectHostApi({BinaryMessenger? binaryMessenger})
: _binaryMessenger = binaryMessenger;

final BinaryMessenger? _binaryMessenger;

static const MessageCodec<Object?> codec = _JavaObjectHostApiCodec();

Future<void> dispose(int arg_identifier) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.JavaObjectHostApi.dispose', codec,
binaryMessenger: _binaryMessenger);
final Map<Object?, Object?>? replyMap =
await channel.send(<Object?>[arg_identifier]) as Map<Object?, Object?>?;
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyMap['error'] != null) {
final Map<Object?, Object?> error =
(replyMap['error'] as Map<Object?, Object?>?)!;
throw PlatformException(
code: (error['code'] as String?)!,
message: error['message'] as String?,
details: error['details'],
);
} else {
return;
}
}
}

class _JavaObjectFlutterApiCodec extends StandardMessageCodec {
const _JavaObjectFlutterApiCodec();
}

abstract class JavaObjectFlutterApi {
static const MessageCodec<Object?> codec = _JavaObjectFlutterApiCodec();

void dispose(int identifier);
static void setup(JavaObjectFlutterApi? api,
{BinaryMessenger? binaryMessenger}) {
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.JavaObjectFlutterApi.dispose', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.JavaObjectFlutterApi.dispose was null.');
final List<Object?> args = (message as List<Object?>?)!;
final int? arg_identifier = (args[0] as int?);
assert(arg_identifier != null,
'Argument for dev.flutter.pigeon.JavaObjectFlutterApi.dispose was null, expected non-null int.');
api.dispose(arg_identifier!);
return;
});
}
}
}
}

class _CookieManagerHostApiCodec extends StandardMessageCodec {
const _CookieManagerHostApiCodec();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@ WebResourceError _toWebResourceError(WebResourceErrorData data) {
class AndroidWebViewFlutterApis {
/// Creates a [AndroidWebViewFlutterApis].
AndroidWebViewFlutterApis({
JavaObjectFlutterApiImpl? javaObjectFlutterApi,
DownloadListenerFlutterApiImpl? downloadListenerFlutterApi,
WebViewClientFlutterApiImpl? webViewClientFlutterApi,
WebChromeClientFlutterApiImpl? webChromeClientFlutterApi,
JavaScriptChannelFlutterApiImpl? javaScriptChannelFlutterApi,
}) {
this.javaObjectFlutterApi =
javaObjectFlutterApi ?? JavaObjectFlutterApiImpl();
this.downloadListenerFlutterApi =
downloadListenerFlutterApi ?? DownloadListenerFlutterApiImpl();
this.webViewClientFlutterApi =
Expand All @@ -58,6 +61,9 @@ class AndroidWebViewFlutterApis {
/// This should only be changed for testing purposes.
static AndroidWebViewFlutterApis instance = AndroidWebViewFlutterApis();

/// Handles callbacks methods for the native Java Object class.
late final JavaObjectFlutterApi javaObjectFlutterApi;

/// Flutter Api for [DownloadListener].
late final DownloadListenerFlutterApiImpl downloadListenerFlutterApi;

Expand All @@ -73,6 +79,7 @@ class AndroidWebViewFlutterApis {
/// Ensures all the Flutter APIs have been setup to receive calls from native code.
void ensureSetUp() {
if (!_haveBeenSetUp) {
JavaObjectFlutterApi.setup(javaObjectFlutterApi);
DownloadListenerFlutterApi.setup(downloadListenerFlutterApi);
WebViewClientFlutterApi.setup(webViewClientFlutterApi);
WebChromeClientFlutterApi.setup(webChromeClientFlutterApi);
Expand All @@ -82,6 +89,40 @@ class AndroidWebViewFlutterApis {
}
}

/// Handles methods calls to the native Java Object class.
class JavaObjectHostApiImpl extends JavaObjectHostApi {
/// Constructs a [JavaObjectHostApiImpl].
JavaObjectHostApiImpl({
this.binaryMessenger,
InstanceManager? instanceManager,
}) : instanceManager = instanceManager ?? JavaObject.globalInstanceManager,
super(binaryMessenger: binaryMessenger);

/// Receives binary data across the Flutter platform barrier.
///
/// If it is null, the default BinaryMessenger will be used which routes to
/// the host platform.
final BinaryMessenger? binaryMessenger;

/// Maintains instances stored to communicate with native language objects.
final InstanceManager instanceManager;
}

/// Handles callbacks methods for the native Java Object class.
class JavaObjectFlutterApiImpl implements JavaObjectFlutterApi {
/// Constructs a [JavaObjectFlutterApiImpl].
JavaObjectFlutterApiImpl({InstanceManager? instanceManager})
: instanceManager = instanceManager ?? JavaObject.globalInstanceManager;

/// Maintains instances stored to communicate with native language objects.
final InstanceManager instanceManager;

@override
void dispose(int identifier) {
instanceManager.remove(identifier);
}
}

/// Host api implementation for [WebView].
class WebViewHostApiImpl extends WebViewHostApi {
/// Constructs a [WebViewHostApiImpl].
Expand Down
Loading