From 4488f58acfd7d8b7eca1ec31b0dac116ff7302d2 Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Tue, 16 Jan 2018 13:14:01 -0500 Subject: [PATCH] Set _imageInfo to null BEFORE adding listener to new ImageStream (#13825) * Set _imageInfo to null before adding listener to new ImageStream Fixes an edge case where switching the ImageStream to an already completed ImageStream caused the Image widget to show nothing. ImageStreamCompleter calls the listener during addListener if their image is already loaded. * Fix whitespace * Add test to verify correct behavior * Added test from mravn-google's PR --- packages/flutter/lib/src/widgets/image.dart | 6 +- packages/flutter/test/widgets/image_test.dart | 62 +++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/packages/flutter/lib/src/widgets/image.dart b/packages/flutter/lib/src/widgets/image.dart index eb4408e2b2..f1655812c8 100644 --- a/packages/flutter/lib/src/widgets/image.dart +++ b/packages/flutter/lib/src/widgets/image.dart @@ -545,12 +545,12 @@ class _ImageState extends State { if (_isListeningToStream) _imageStream.removeListener(_handleImageChanged); + if (!widget.gaplessPlayback) + setState(() { _imageInfo = null; }); + _imageStream = newStream; if (_isListeningToStream) _imageStream.addListener(_handleImageChanged); - - if (!widget.gaplessPlayback) - setState(() { _imageInfo = null; }); } void _listenToStream() { diff --git a/packages/flutter/test/widgets/image_test.dart b/packages/flutter/test/widgets/image_test.dart index bd01a10442..a814a7c58c 100644 --- a/packages/flutter/test/widgets/image_test.dart +++ b/packages/flutter/test/widgets/image_test.dart @@ -363,6 +363,68 @@ void main() { expect(imageStreamCompleter.listeners.length, 0); }); + testWidgets('Verify Image shows correct RenderImage when changing to an already completed provider', (WidgetTester tester) async { + final GlobalKey key = new GlobalKey(); + + final TestImageProvider imageProvider1 = new TestImageProvider(); + final TestImageProvider imageProvider2 = new TestImageProvider(); + + await tester.pumpWidget( + new Container( + key: key, + child: new Image( + image: imageProvider1 + ) + ), + null, + EnginePhase.layout + ); + RenderImage renderImage = key.currentContext.findRenderObject(); + expect(renderImage.image, isNull); + + imageProvider1.complete(); + imageProvider2.complete(); + await tester.idle(); // resolve the future from the image provider + await tester.pump(null, EnginePhase.layout); + + renderImage = key.currentContext.findRenderObject(); + expect(renderImage.image, isNotNull); + + final ui.Image oldImage = renderImage.image; + + await tester.pumpWidget( + new Container( + key: key, + child: new Image( + image: imageProvider2 + ) + ), + null, + EnginePhase.layout + ); + + renderImage = key.currentContext.findRenderObject(); + expect(renderImage.image, isNotNull); + expect(renderImage.image, isNot(equals(oldImage))); + }); + + testWidgets('Image State can be reconfigured to use another image', (WidgetTester tester) async { + final Image image1 = new Image(image: new TestImageProvider()..complete(), width: 10.0); + final Image image2 = new Image(image: new TestImageProvider()..complete(), width: 20.0); + + final Column column = new Column(children: [image1, image2]); + await tester.pumpWidget(column, null, EnginePhase.layout); + + final Column columnSwapped = new Column(children: [image2, image1]); + await tester.pumpWidget(columnSwapped, null, EnginePhase.layout); + + final List renderObjects = tester.renderObjectList(find.byType(Image)).toList(); + expect(renderObjects, hasLength(2)); + expect(renderObjects[0].image, isNotNull); + expect(renderObjects[0].width, 20.0); + expect(renderObjects[1].image, isNotNull); + expect(renderObjects[1].width, 10.0); + }); } class TestImageProvider extends ImageProvider {