From 53727866e6aafbda25c08e1ef73f3da39d4dd427 Mon Sep 17 00:00:00 2001 From: TruongSinh Tran-Nguyen Date: Thu, 3 Jan 2019 12:05:53 +0700 Subject: [PATCH] fix #25143 Successive calls to `precacheImage()` throw an exception (#25159) --- AUTHORS | 1 + packages/flutter/lib/src/widgets/image.dart | 3 ++- packages/flutter/test/widgets/image_test.dart | 22 +++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 67cc5d456d..ec25d3e7a3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -32,3 +32,4 @@ Chema Molins Stefan Mitev Jasper van Riet Mattijs Fuijkschot +TruongSinh Tran-Nguyen diff --git a/packages/flutter/lib/src/widgets/image.dart b/packages/flutter/lib/src/widgets/image.dart index 9711823ab8..b7d068a522 100644 --- a/packages/flutter/lib/src/widgets/image.dart +++ b/packages/flutter/lib/src/widgets/image.dart @@ -83,9 +83,11 @@ Future precacheImage( final ImageStream stream = provider.resolve(config); void listener(ImageInfo image, bool sync) { completer.complete(); + stream.removeListener(listener); } void errorListener(dynamic exception, StackTrace stackTrace) { completer.complete(); + stream.removeListener(listener); if (onError != null) { onError(exception, stackTrace); } else { @@ -99,7 +101,6 @@ Future precacheImage( } } stream.addListener(listener, onError: errorListener); - completer.future.then((void value) { stream.removeListener(listener); }); return completer.future; } diff --git a/packages/flutter/test/widgets/image_test.dart b/packages/flutter/test/widgets/image_test.dart index 7c17a95e1b..f0b9ea4b59 100644 --- a/packages/flutter/test/widgets/image_test.dart +++ b/packages/flutter/test/widgets/image_test.dart @@ -621,6 +621,28 @@ void main() { expect(isSync, isTrue); }); + testWidgets('Precache remove listeners immediately after future completes, does not crash on successive calls #25143', (WidgetTester tester) async { + final TestImageStreamCompleter imageStreamCompleter = TestImageStreamCompleter(); + final TestImageProvider provider = TestImageProvider(streamCompleter: imageStreamCompleter); + + await tester.pumpWidget( + Builder( + builder: (BuildContext context) { + precacheImage(provider, context); + return Container(); + } + ) + ); + + expect(imageStreamCompleter.listeners.length, 2); + imageStreamCompleter.listeners.keys.toList()[1](null, null); + + expect(imageStreamCompleter.listeners.length, 1); + imageStreamCompleter.listeners.keys.toList()[0](null, null); + + expect(imageStreamCompleter.listeners.length, 0); + }); + testWidgets('Precache completes with onError on error', (WidgetTester tester) async { dynamic capturedException; StackTrace capturedStackTrace;