Skip to content

Commit e19094a

Browse files
authored
Use efficient operations when copying bytes between Dart and Java (#1019)
1 parent d7e4375 commit e19094a

File tree

8 files changed

+124
-1439
lines changed

8 files changed

+124
-1439
lines changed

pkgs/cronet_http/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.4.0-jni
2+
3+
* Use more efficient operations when copying bytes between Java and Dart.
4+
15
## 0.3.0-jni
26

37
* Switch to using `package:jnigen` for bindings to Cronet

pkgs/cronet_http/android/build.gradle

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ android {
4343
defaultConfig {
4444
minSdkVersion 16
4545
}
46+
47+
defaultConfig {
48+
consumerProguardFiles 'consumer-rules.pro'
49+
}
50+
51+
buildTypes {
52+
release {
53+
minifyEnabled false
54+
}
55+
}
4656
}
4757

4858
dependencies {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-keep class io.flutter.plugins.cronet_http.** { *; }

pkgs/cronet_http/example/android/app/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,7 @@ flutter {
6767

6868
dependencies {
6969
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
70+
// ""com.google.android.gms:play-services-cronet" is only present so that
71+
// `jnigen` will work. Applications should not include this line.
72+
implementation "com.google.android.gms:play-services-cronet:18.0.1"
7073
}

pkgs/cronet_http/jnigen.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ android_sdk_config:
77
add_gradle_deps: true
88
android_example: 'example/'
99

10-
suspend_fun_to_async: true
11-
1210
output:
1311
bindings_type: dart_only
1412
dart:
@@ -18,8 +16,6 @@ output:
1816
classes:
1917
- 'io.flutter.plugins.cronet_http.UrlRequestCallbackProxy'
2018
- 'java.net.URL'
21-
- 'java.nio.Buffer'
22-
- 'java.nio.ByteBuffer'
2319
- 'java.util.concurrent.Executors'
2420
- 'org.chromium.net.CronetEngine'
2521
- 'org.chromium.net.CronetException'

pkgs/cronet_http/lib/src/cronet_client.dart

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414
library;
1515

1616
import 'dart:async';
17-
import 'dart:typed_data';
1817

1918
import 'package:http/http.dart';
2019
import 'package:jni/jni.dart';
2120

2221
import 'jni/jni_bindings.dart' as jb;
2322

2423
final _digitRegex = RegExp(r'^\d+$');
24+
const _bufferSize = 10 * 1024; // The size of the Cronet read buffer.
2525

2626
/// The type of caching to use when making HTTP requests.
2727
enum CacheMode {
@@ -138,7 +138,7 @@ Map<String, String> _cronetToClientHeaders(
138138
jb.UrlRequestCallbackProxy_UrlRequestCallbackInterface _urlRequestCallbacks(
139139
BaseRequest request, Completer<StreamedResponse> responseCompleter) {
140140
StreamController<List<int>>? responseStream;
141-
jb.ByteBuffer? byteBuffer;
141+
JByteBuffer? jByteBuffer;
142142
var numRedirects = 0;
143143

144144
// The order of callbacks generated by Cronet is documented here:
@@ -175,8 +175,8 @@ jb.UrlRequestCallbackProxy_UrlRequestCallbackInterface _urlRequestCallbacks(
175175
headers: responseHeaders,
176176
));
177177

178-
byteBuffer = jb.ByteBuffer.allocateDirect(1024 * 1024);
179-
urlRequest.read(byteBuffer!);
178+
jByteBuffer = JByteBuffer.allocateDirect(_bufferSize);
179+
urlRequest.read(jByteBuffer!);
180180
},
181181
onRedirectReceived: (urlRequest, responseInfo, newLocationUrl) {
182182
if (!request.followRedirects) {
@@ -204,20 +204,15 @@ jb.UrlRequestCallbackProxy_UrlRequestCallbackInterface _urlRequestCallbacks(
204204
},
205205
onReadCompleted: (urlRequest, responseInfo, byteBuffer) {
206206
byteBuffer.flip();
207+
responseStream!
208+
.add(jByteBuffer!.asUint8List().sublist(0, byteBuffer.remaining));
207209

208-
final remaining = byteBuffer.remaining();
209-
final data = Uint8List(remaining);
210-
// TODO: Use a more efficient approach when
211-
// https://github.com/dart-lang/jnigen/issues/387 is fixed.
212-
for (var i = 0; i < remaining; ++i) {
213-
data[i] = byteBuffer.get1(i);
214-
}
215-
responseStream!.add(data);
216210
byteBuffer.clear();
217211
urlRequest.read(byteBuffer);
218212
},
219213
onSucceeded: (urlRequest, responseInfo) {
220214
responseStream!.sink.close();
215+
jByteBuffer?.release();
221216
},
222217
onFailed: (urlRequest, responseInfo, cronetException) {
223218
final error = ClientException(
@@ -228,6 +223,7 @@ jb.UrlRequestCallbackProxy_UrlRequestCallbackInterface _urlRequestCallbacks(
228223
responseStream!.addError(error);
229224
responseStream!.close();
230225
}
226+
jByteBuffer?.release();
231227
},
232228
));
233229
}
@@ -333,14 +329,8 @@ class CronetClient extends BaseClient {
333329
headers.forEach((k, v) => builder.addHeader(k.toJString(), v.toJString()));
334330

335331
if (body.isNotEmpty) {
336-
// TODO: Use a more efficient approach when
337-
// https://github.com/dart-lang/jnigen/issues/387 is fixed.
338-
final bodyBytes = JArray(jbyte.type, body.length);
339-
for (var i = 0; i < body.length; ++i) {
340-
bodyBytes[i] = body[i];
341-
}
342332
builder.setUploadDataProvider(
343-
jb.UploadDataProviders.create4(bodyBytes), _executor);
333+
jb.UploadDataProviders.create2(body.toJByteBuffer()), _executor);
344334
}
345335
builder.build().start();
346336
return responseCompleter.future;

0 commit comments

Comments
 (0)