Created method to report ImageChunkEvents (#55044)

This commit is contained in:
Rene Floor 2020-04-22 08:18:01 +02:00 committed by GitHub
parent 5c5bb485a0
commit 0763a57a98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 15 deletions

View file

@ -516,6 +516,23 @@ abstract class ImageStreamCompleter with Diagnosticable {
}
}
/// Calls all the registered [ImageChunkListener]s (listeners with an
/// [ImageStreamListener.onChunk] specified) to notify them of a new
/// [ImageChunkEvent].
@protected
void reportImageChunkEvent(ImageChunkEvent event){
if (hasListeners) {
// Make a copy to allow for concurrent modification.
final List<ImageChunkListener> localListeners = _listeners
.map<ImageChunkListener>((ImageStreamListener listener) => listener.onChunk)
.where((ImageChunkListener chunkListener) => chunkListener != null)
.toList();
for (final ImageChunkListener listener in localListeners) {
listener(event);
}
}
}
/// Accumulates a list of strings describing the object's state. Subclasses
/// should override this to have their information included in [toString].
@override
@ -626,19 +643,8 @@ class MultiFrameImageStreamCompleter extends ImageStreamCompleter {
);
});
if (chunkEvents != null) {
chunkEvents.listen(
(ImageChunkEvent event) {
if (hasListeners) {
// Make a copy to allow for concurrent modification.
final List<ImageChunkListener> localListeners = _listeners
.map<ImageChunkListener>((ImageStreamListener listener) => listener.onChunk)
.where((ImageChunkListener chunkListener) => chunkListener != null)
.toList();
for (final ImageChunkListener listener in localListeners) {
listener(event);
}
}
}, onError: (dynamic error, StackTrace stack) {
chunkEvents.listen(reportImageChunkEvent,
onError: (dynamic error, StackTrace stack) {
reportError(
context: ErrorDescription('loading an image'),
exception: error,

View file

@ -78,6 +78,17 @@ class MockCodec implements Codec {
}
class FakeEventReportingImageStreamCompleter extends ImageStreamCompleter {
FakeEventReportingImageStreamCompleter({Stream<ImageChunkEvent> chunkEvents,}) {
if (chunkEvents != null) {
chunkEvents.listen((ImageChunkEvent event) {
reportImageChunkEvent(event);
},
);
}
}
}
void main() {
testWidgets('Codec future fails', (WidgetTester tester) async {
final Completer<Codec> completer = Completer<Codec>();
@ -128,7 +139,54 @@ void main() {
expect(mockCodec.numFramesAsked, 1);
});
testWidgets('Chunk events are delivered', (WidgetTester tester) async {
testWidgets('Chunk events of base ImageStreamCompleter are delivered', (WidgetTester tester) async {
final List<ImageChunkEvent> chunkEvents = <ImageChunkEvent>[];
final StreamController<ImageChunkEvent> streamController = StreamController<ImageChunkEvent>();
final ImageStreamCompleter imageStream = FakeEventReportingImageStreamCompleter(
chunkEvents: streamController.stream,
);
imageStream.addListener(ImageStreamListener(
(ImageInfo image, bool synchronousCall) { },
onChunk: (ImageChunkEvent event) {
chunkEvents.add(event);
},
));
streamController.add(const ImageChunkEvent(cumulativeBytesLoaded: 1, expectedTotalBytes: 3));
streamController.add(const ImageChunkEvent(cumulativeBytesLoaded: 2, expectedTotalBytes: 3));
await tester.idle();
expect(chunkEvents.length, 2);
expect(chunkEvents[0].cumulativeBytesLoaded, 1);
expect(chunkEvents[0].expectedTotalBytes, 3);
expect(chunkEvents[1].cumulativeBytesLoaded, 2);
expect(chunkEvents[1].expectedTotalBytes, 3);
});
testWidgets('Chunk events of base ImageStreamCompleter are not buffered before listener registration', (WidgetTester tester) async {
final List<ImageChunkEvent> chunkEvents = <ImageChunkEvent>[];
final StreamController<ImageChunkEvent> streamController = StreamController<ImageChunkEvent>();
final ImageStreamCompleter imageStream = FakeEventReportingImageStreamCompleter(
chunkEvents: streamController.stream,
);
streamController.add(const ImageChunkEvent(cumulativeBytesLoaded: 1, expectedTotalBytes: 3));
await tester.idle();
imageStream.addListener(ImageStreamListener(
(ImageInfo image, bool synchronousCall) { },
onChunk: (ImageChunkEvent event) {
chunkEvents.add(event);
},
));
streamController.add(const ImageChunkEvent(cumulativeBytesLoaded: 2, expectedTotalBytes: 3));
await tester.idle();
expect(chunkEvents.length, 1);
expect(chunkEvents[0].cumulativeBytesLoaded, 2);
expect(chunkEvents[0].expectedTotalBytes, 3);
});
testWidgets('Chunk events of MultiFrameImageStreamCompleter are delivered', (WidgetTester tester) async {
final List<ImageChunkEvent> chunkEvents = <ImageChunkEvent>[];
final Completer<Codec> completer = Completer<Codec>();
final StreamController<ImageChunkEvent> streamController = StreamController<ImageChunkEvent>();
@ -155,7 +213,7 @@ void main() {
expect(chunkEvents[1].expectedTotalBytes, 3);
});
testWidgets('Chunk events are not buffered before listener registration', (WidgetTester tester) async {
testWidgets('Chunk events of MultiFrameImageStreamCompleter are not buffered before listener registration', (WidgetTester tester) async {
final List<ImageChunkEvent> chunkEvents = <ImageChunkEvent>[];
final Completer<Codec> completer = Completer<Codec>();
final StreamController<ImageChunkEvent> streamController = StreamController<ImageChunkEvent>();