Skip to content

Commit 2132d15

Browse files
bparrishMinesmoisefeelin
authored andcommitted
[webview_flutter_android] Adds dispose methods for HostApi and FlutterApi of JavaObject (flutter#6172)
1 parent b4416a0 commit 2132d15

File tree

12 files changed

+406
-6
lines changed

12 files changed

+406
-6
lines changed

packages/webview_flutter/webview_flutter_android/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.9.5
2+
3+
* Adds dispose methods for HostApi and FlutterApi of JavaObject.
4+
15
## 2.9.4
26

37
* Fixes avoid_redundant_argument_values lint warnings and minor typos.

packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
// Autogenerated from Pigeon (v3.0.3), do not edit directly.
4+
// Autogenerated from Pigeon (v3.2.0), do not edit directly.
55
// See also: https://pub.dev/packages/pigeon
66

77
package io.flutter.plugins.webviewflutter;
@@ -271,6 +271,87 @@ public interface Result<T> {
271271
void error(Throwable error);
272272
}
273273

274+
private static class JavaObjectHostApiCodec extends StandardMessageCodec {
275+
public static final JavaObjectHostApiCodec INSTANCE = new JavaObjectHostApiCodec();
276+
277+
private JavaObjectHostApiCodec() {}
278+
}
279+
280+
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
281+
public interface JavaObjectHostApi {
282+
void dispose(@NonNull Long identifier);
283+
284+
/** The codec used by JavaObjectHostApi. */
285+
static MessageCodec<Object> getCodec() {
286+
return JavaObjectHostApiCodec.INSTANCE;
287+
}
288+
289+
/**
290+
* Sets up an instance of `JavaObjectHostApi` to handle messages through the `binaryMessenger`.
291+
*/
292+
static void setup(BinaryMessenger binaryMessenger, JavaObjectHostApi api) {
293+
{
294+
BasicMessageChannel<Object> channel =
295+
new BasicMessageChannel<>(
296+
binaryMessenger, "dev.flutter.pigeon.JavaObjectHostApi.dispose", getCodec());
297+
if (api != null) {
298+
channel.setMessageHandler(
299+
(message, reply) -> {
300+
Map<String, Object> wrapped = new HashMap<>();
301+
try {
302+
ArrayList<Object> args = (ArrayList<Object>) message;
303+
Number identifierArg = (Number) args.get(0);
304+
if (identifierArg == null) {
305+
throw new NullPointerException("identifierArg unexpectedly null.");
306+
}
307+
api.dispose((identifierArg == null) ? null : identifierArg.longValue());
308+
wrapped.put("result", null);
309+
} catch (Error | RuntimeException exception) {
310+
wrapped.put("error", wrapError(exception));
311+
}
312+
reply.reply(wrapped);
313+
});
314+
} else {
315+
channel.setMessageHandler(null);
316+
}
317+
}
318+
}
319+
}
320+
321+
private static class JavaObjectFlutterApiCodec extends StandardMessageCodec {
322+
public static final JavaObjectFlutterApiCodec INSTANCE = new JavaObjectFlutterApiCodec();
323+
324+
private JavaObjectFlutterApiCodec() {}
325+
}
326+
327+
/** Generated class from Pigeon that represents Flutter messages that can be called from Java. */
328+
public static class JavaObjectFlutterApi {
329+
private final BinaryMessenger binaryMessenger;
330+
331+
public JavaObjectFlutterApi(BinaryMessenger argBinaryMessenger) {
332+
this.binaryMessenger = argBinaryMessenger;
333+
}
334+
335+
public interface Reply<T> {
336+
void reply(T reply);
337+
}
338+
339+
static MessageCodec<Object> getCodec() {
340+
return JavaObjectFlutterApiCodec.INSTANCE;
341+
}
342+
343+
public void dispose(@NonNull Long identifierArg, Reply<Void> callback) {
344+
BasicMessageChannel<Object> channel =
345+
new BasicMessageChannel<>(
346+
binaryMessenger, "dev.flutter.pigeon.JavaObjectFlutterApi.dispose", getCodec());
347+
channel.send(
348+
new ArrayList<Object>(Arrays.asList(identifierArg)),
349+
channelReply -> {
350+
callback.reply(null);
351+
});
352+
}
353+
}
354+
274355
private static class CookieManagerHostApiCodec extends StandardMessageCodec {
275356
public static final CookieManagerHostApiCodec INSTANCE = new CookieManagerHostApiCodec();
276357

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
package io.flutter.plugins.webviewflutter;
6+
7+
import androidx.annotation.NonNull;
8+
9+
/**
10+
* A pigeon Host API implementation that handles creating {@link Object}s and invoking its static
11+
* and instance methods.
12+
*
13+
* <p>{@link Object} instances created by {@link JavaObjectHostApiImpl} are used to intercommunicate
14+
* with a paired Dart object.
15+
*/
16+
public class JavaObjectHostApiImpl implements GeneratedAndroidWebView.JavaObjectHostApi {
17+
private final InstanceManager instanceManager;
18+
19+
/**
20+
* Constructs a {@link JavaObjectHostApiImpl}.
21+
*
22+
* @param instanceManager maintains instances stored to communicate with Dart objects
23+
*/
24+
public JavaObjectHostApiImpl(InstanceManager instanceManager) {
25+
this.instanceManager = instanceManager;
26+
}
27+
28+
@Override
29+
public void dispose(@NonNull Long identifier) {
30+
instanceManager.remove(identifier);
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
package io.flutter.plugins.webviewflutter;
6+
7+
import static org.junit.Assert.assertNull;
8+
9+
import org.junit.Test;
10+
11+
public class JavaObjectHostApiTest {
12+
@Test
13+
public void dispose() {
14+
final InstanceManager instanceManager = InstanceManager.open(identifier -> {});
15+
16+
final JavaObjectHostApiImpl hostApi = new JavaObjectHostApiImpl(instanceManager);
17+
18+
Object object = new Object();
19+
instanceManager.addDartCreatedInstance(object, 0);
20+
21+
// To free object for garbage collection.
22+
//noinspection UnusedAssignment
23+
object = null;
24+
25+
hostApi.dispose(0L);
26+
Runtime.getRuntime().gc();
27+
28+
assertNull(instanceManager.getInstance(0));
29+
30+
instanceManager.close();
31+
}
32+
}

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

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import 'dart:typed_data';
1313
import 'dart:ui';
1414

1515
import 'package:flutter/foundation.dart';
16+
import 'package:flutter/services.dart' show BinaryMessenger;
1617
import 'package:flutter/widgets.dart' show AndroidViewSurface;
1718

1819
import 'android_webview.pigeon.dart';
@@ -22,17 +23,36 @@ import 'instance_manager.dart';
2223
/// Root of the Java class hierarchy.
2324
///
2425
/// See https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html.
25-
abstract class JavaObject with Copyable {
26+
class JavaObject with Copyable {
2627
/// Constructs a [JavaObject] without creating the associated Java object.
2728
///
2829
/// This should only be used by subclasses created by this library or to
2930
/// create copies.
30-
JavaObject.detached();
31+
JavaObject.detached({
32+
BinaryMessenger? binaryMessenger,
33+
InstanceManager? instanceManager,
34+
}) : _api = JavaObjectHostApiImpl(
35+
binaryMessenger: binaryMessenger,
36+
instanceManager: instanceManager,
37+
);
3138

3239
/// Global instance of [InstanceManager].
3340
static final InstanceManager globalInstanceManager = InstanceManager(
3441
onWeakReferenceRemoved: (_) {},
3542
);
43+
44+
/// Pigeon Host Api implementation for [JavaObject].
45+
final JavaObjectHostApiImpl _api;
46+
47+
/// Release the reference to a native Java instance.
48+
static void dispose(JavaObject instance) {
49+
instance._api.instanceManager.removeWeakReference(instance);
50+
}
51+
52+
@override
53+
JavaObject copy() {
54+
return JavaObject.detached();
55+
}
3656
}
3757

3858
/// An Android View that displays web pages.

packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
// Autogenerated from Pigeon (v3.0.3), do not edit directly.
4+
// Autogenerated from Pigeon (v3.2.0), do not edit directly.
55
// See also: https://pub.dev/packages/pigeon
66
// 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
77
// @dart = 2.12
@@ -78,6 +78,78 @@ class WebResourceErrorData {
7878
}
7979
}
8080

81+
class _JavaObjectHostApiCodec extends StandardMessageCodec {
82+
const _JavaObjectHostApiCodec();
83+
}
84+
85+
class JavaObjectHostApi {
86+
/// Constructor for [JavaObjectHostApi]. The [binaryMessenger] named argument is
87+
/// available for dependency injection. If it is left null, the default
88+
/// BinaryMessenger will be used which routes to the host platform.
89+
JavaObjectHostApi({BinaryMessenger? binaryMessenger})
90+
: _binaryMessenger = binaryMessenger;
91+
92+
final BinaryMessenger? _binaryMessenger;
93+
94+
static const MessageCodec<Object?> codec = _JavaObjectHostApiCodec();
95+
96+
Future<void> dispose(int arg_identifier) async {
97+
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
98+
'dev.flutter.pigeon.JavaObjectHostApi.dispose', codec,
99+
binaryMessenger: _binaryMessenger);
100+
final Map<Object?, Object?>? replyMap =
101+
await channel.send(<Object?>[arg_identifier]) as Map<Object?, Object?>?;
102+
if (replyMap == null) {
103+
throw PlatformException(
104+
code: 'channel-error',
105+
message: 'Unable to establish connection on channel.',
106+
);
107+
} else if (replyMap['error'] != null) {
108+
final Map<Object?, Object?> error =
109+
(replyMap['error'] as Map<Object?, Object?>?)!;
110+
throw PlatformException(
111+
code: (error['code'] as String?)!,
112+
message: error['message'] as String?,
113+
details: error['details'],
114+
);
115+
} else {
116+
return;
117+
}
118+
}
119+
}
120+
121+
class _JavaObjectFlutterApiCodec extends StandardMessageCodec {
122+
const _JavaObjectFlutterApiCodec();
123+
}
124+
125+
abstract class JavaObjectFlutterApi {
126+
static const MessageCodec<Object?> codec = _JavaObjectFlutterApiCodec();
127+
128+
void dispose(int identifier);
129+
static void setup(JavaObjectFlutterApi? api,
130+
{BinaryMessenger? binaryMessenger}) {
131+
{
132+
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
133+
'dev.flutter.pigeon.JavaObjectFlutterApi.dispose', codec,
134+
binaryMessenger: binaryMessenger);
135+
if (api == null) {
136+
channel.setMessageHandler(null);
137+
} else {
138+
channel.setMessageHandler((Object? message) async {
139+
assert(message != null,
140+
'Argument for dev.flutter.pigeon.JavaObjectFlutterApi.dispose was null.');
141+
final List<Object?> args = (message as List<Object?>?)!;
142+
final int? arg_identifier = (args[0] as int?);
143+
assert(arg_identifier != null,
144+
'Argument for dev.flutter.pigeon.JavaObjectFlutterApi.dispose was null, expected non-null int.');
145+
api.dispose(arg_identifier!);
146+
return;
147+
});
148+
}
149+
}
150+
}
151+
}
152+
81153
class _CookieManagerHostApiCodec extends StandardMessageCodec {
82154
const _CookieManagerHostApiCodec();
83155
}

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,14 @@ WebResourceError _toWebResourceError(WebResourceErrorData data) {
3636
class AndroidWebViewFlutterApis {
3737
/// Creates a [AndroidWebViewFlutterApis].
3838
AndroidWebViewFlutterApis({
39+
JavaObjectFlutterApiImpl? javaObjectFlutterApi,
3940
DownloadListenerFlutterApiImpl? downloadListenerFlutterApi,
4041
WebViewClientFlutterApiImpl? webViewClientFlutterApi,
4142
WebChromeClientFlutterApiImpl? webChromeClientFlutterApi,
4243
JavaScriptChannelFlutterApiImpl? javaScriptChannelFlutterApi,
4344
}) {
45+
this.javaObjectFlutterApi =
46+
javaObjectFlutterApi ?? JavaObjectFlutterApiImpl();
4447
this.downloadListenerFlutterApi =
4548
downloadListenerFlutterApi ?? DownloadListenerFlutterApiImpl();
4649
this.webViewClientFlutterApi =
@@ -58,6 +61,9 @@ class AndroidWebViewFlutterApis {
5861
/// This should only be changed for testing purposes.
5962
static AndroidWebViewFlutterApis instance = AndroidWebViewFlutterApis();
6063

64+
/// Handles callbacks methods for the native Java Object class.
65+
late final JavaObjectFlutterApi javaObjectFlutterApi;
66+
6167
/// Flutter Api for [DownloadListener].
6268
late final DownloadListenerFlutterApiImpl downloadListenerFlutterApi;
6369

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

92+
/// Handles methods calls to the native Java Object class.
93+
class JavaObjectHostApiImpl extends JavaObjectHostApi {
94+
/// Constructs a [JavaObjectHostApiImpl].
95+
JavaObjectHostApiImpl({
96+
this.binaryMessenger,
97+
InstanceManager? instanceManager,
98+
}) : instanceManager = instanceManager ?? JavaObject.globalInstanceManager,
99+
super(binaryMessenger: binaryMessenger);
100+
101+
/// Receives binary data across the Flutter platform barrier.
102+
///
103+
/// If it is null, the default BinaryMessenger will be used which routes to
104+
/// the host platform.
105+
final BinaryMessenger? binaryMessenger;
106+
107+
/// Maintains instances stored to communicate with native language objects.
108+
final InstanceManager instanceManager;
109+
}
110+
111+
/// Handles callbacks methods for the native Java Object class.
112+
class JavaObjectFlutterApiImpl implements JavaObjectFlutterApi {
113+
/// Constructs a [JavaObjectFlutterApiImpl].
114+
JavaObjectFlutterApiImpl({InstanceManager? instanceManager})
115+
: instanceManager = instanceManager ?? JavaObject.globalInstanceManager;
116+
117+
/// Maintains instances stored to communicate with native language objects.
118+
final InstanceManager instanceManager;
119+
120+
@override
121+
void dispose(int identifier) {
122+
instanceManager.remove(identifier);
123+
}
124+
}
125+
85126
/// Host api implementation for [WebView].
86127
class WebViewHostApiImpl extends WebViewHostApi {
87128
/// Constructs a [WebViewHostApiImpl].

0 commit comments

Comments
 (0)