Skip to content

Commit 4488f58

Browse files
ds84182Hixie
authored andcommitted
Set _imageInfo to null BEFORE adding listener to new ImageStream (flutter#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
1 parent c5050bc commit 4488f58

File tree

2 files changed

+65
-3
lines changed

2 files changed

+65
-3
lines changed

packages/flutter/lib/src/widgets/image.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -545,12 +545,12 @@ class _ImageState extends State<Image> {
545545
if (_isListeningToStream)
546546
_imageStream.removeListener(_handleImageChanged);
547547

548+
if (!widget.gaplessPlayback)
549+
setState(() { _imageInfo = null; });
550+
548551
_imageStream = newStream;
549552
if (_isListeningToStream)
550553
_imageStream.addListener(_handleImageChanged);
551-
552-
if (!widget.gaplessPlayback)
553-
setState(() { _imageInfo = null; });
554554
}
555555

556556
void _listenToStream() {

packages/flutter/test/widgets/image_test.dart

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,68 @@ void main() {
363363
expect(imageStreamCompleter.listeners.length, 0);
364364
});
365365

366+
testWidgets('Verify Image shows correct RenderImage when changing to an already completed provider', (WidgetTester tester) async {
367+
final GlobalKey key = new GlobalKey();
368+
369+
final TestImageProvider imageProvider1 = new TestImageProvider();
370+
final TestImageProvider imageProvider2 = new TestImageProvider();
371+
372+
await tester.pumpWidget(
373+
new Container(
374+
key: key,
375+
child: new Image(
376+
image: imageProvider1
377+
)
378+
),
379+
null,
380+
EnginePhase.layout
381+
);
382+
RenderImage renderImage = key.currentContext.findRenderObject();
383+
expect(renderImage.image, isNull);
384+
385+
imageProvider1.complete();
386+
imageProvider2.complete();
387+
await tester.idle(); // resolve the future from the image provider
388+
await tester.pump(null, EnginePhase.layout);
389+
390+
renderImage = key.currentContext.findRenderObject();
391+
expect(renderImage.image, isNotNull);
392+
393+
final ui.Image oldImage = renderImage.image;
394+
395+
await tester.pumpWidget(
396+
new Container(
397+
key: key,
398+
child: new Image(
399+
image: imageProvider2
400+
)
401+
),
402+
null,
403+
EnginePhase.layout
404+
);
405+
406+
renderImage = key.currentContext.findRenderObject();
407+
expect(renderImage.image, isNotNull);
408+
expect(renderImage.image, isNot(equals(oldImage)));
409+
});
410+
411+
testWidgets('Image State can be reconfigured to use another image', (WidgetTester tester) async {
412+
final Image image1 = new Image(image: new TestImageProvider()..complete(), width: 10.0);
413+
final Image image2 = new Image(image: new TestImageProvider()..complete(), width: 20.0);
414+
415+
final Column column = new Column(children: <Widget>[image1, image2]);
416+
await tester.pumpWidget(column, null, EnginePhase.layout);
417+
418+
final Column columnSwapped = new Column(children: <Widget>[image2, image1]);
419+
await tester.pumpWidget(columnSwapped, null, EnginePhase.layout);
420+
421+
final List<RenderImage> renderObjects = tester.renderObjectList<RenderImage>(find.byType(Image)).toList();
422+
expect(renderObjects, hasLength(2));
423+
expect(renderObjects[0].image, isNotNull);
424+
expect(renderObjects[0].width, 20.0);
425+
expect(renderObjects[1].image, isNotNull);
426+
expect(renderObjects[1].width, 10.0);
427+
});
366428
}
367429

368430
class TestImageProvider extends ImageProvider<TestImageProvider> {

0 commit comments

Comments
 (0)