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
This commit is contained in:
Dwayne Slater
2018-01-16 13:14:01 -05:00
committed by Ian Hickson
parent c5050bc8a9
commit 4488f58acf
2 changed files with 65 additions and 3 deletions

View File

@@ -545,12 +545,12 @@ class _ImageState extends State<Image> {
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() {

View File

@@ -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: <Widget>[image1, image2]);
await tester.pumpWidget(column, null, EnginePhase.layout);
final Column columnSwapped = new Column(children: <Widget>[image2, image1]);
await tester.pumpWidget(columnSwapped, null, EnginePhase.layout);
final List<RenderImage> renderObjects = tester.renderObjectList<RenderImage>(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<TestImageProvider> {