Skip to content

Commit a2a8424

Browse files
authored
Merge pull request cfug#639 from Endebert/patch-1
fix(transformer): reduce memory consumption
2 parents 8b60df6 + 79ee699 commit a2a8424

File tree

1 file changed

+31
-13
lines changed

1 file changed

+31
-13
lines changed

dio/lib/src/transformer.dart

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import 'dart:async';
22
import 'dart:convert';
33
import 'dart:typed_data';
4+
45
import 'package:http_parser/http_parser.dart';
56

67
import 'adapter.dart';
7-
import 'options.dart';
88
import 'dio_error.dart';
99
import 'headers.dart';
10+
import 'options.dart';
1011
import 'utils.dart';
1112

1213
/// [Transformer] allows changes to the request/response data before
@@ -83,21 +84,29 @@ class DefaultTransformer extends Transformer {
8384
}
8485
var completer = Completer();
8586
var stream =
86-
response.stream.transform<Uint8List>(StreamTransformer.fromHandlers(
87+
response.stream.transform<Uint8List>(StreamTransformer.fromHandlers(
8788
handleData: (data, sink) {
88-
sink.add(Uint8List.fromList(data));
89+
sink.add(data);
8990
if (showDownloadProgress) {
9091
received += data.length;
9192
options.onReceiveProgress(received, length);
9293
}
9394
},
9495
));
95-
var buffer = <int>[];
96-
StreamSubscription subscription;
97-
subscription = stream.listen(
98-
(element) => buffer.addAll(element),
99-
onError: (e) => completer.completeError(e),
100-
onDone: () => completer.complete(),
96+
// let's keep references to the data chunks and concatenate them later
97+
final List<Uint8List> chunks = [];
98+
int finalSize = 0;
99+
StreamSubscription subscription = stream.listen(
100+
(chunk) {
101+
finalSize += chunk.length;
102+
chunks.add(chunk);
103+
},
104+
onError: (e) {
105+
completer.completeError(e);
106+
},
107+
onDone: () {
108+
completer.complete();
109+
},
101110
cancelOnError: true,
102111
);
103112
// ignore: unawaited_futures
@@ -119,13 +128,22 @@ class DefaultTransformer extends Transformer {
119128
} else {
120129
await completer.future;
121130
}
122-
if (options.responseType == ResponseType.bytes) return buffer;
131+
// we create a final Uint8List and copy all chunks into it
132+
final responseBytes = Uint8List(finalSize);
133+
int chunkOffset = 0;
134+
for (var chunk in chunks) {
135+
responseBytes.setAll(chunkOffset, chunk);
136+
chunkOffset += chunk.length;
137+
}
138+
139+
if (options.responseType == ResponseType.bytes) return responseBytes;
140+
123141
String responseBody;
124142
if (options.responseDecoder != null) {
125-
responseBody =
126-
options.responseDecoder(buffer, options, response..stream = null);
143+
responseBody = options.responseDecoder(
144+
responseBytes, options, response..stream = null);
127145
} else {
128-
responseBody = utf8.decode(buffer, allowMalformed: true);
146+
responseBody = utf8.decode(responseBytes, allowMalformed: true);
129147
}
130148
if (responseBody != null &&
131149
responseBody.isNotEmpty &&

0 commit comments

Comments
 (0)