Unverified Commit 5be7e49d authored by fzyzcjy's avatar fzyzcjy Committed by GitHub

Fix Image's logical flow which disposes its image too early, causing errors...

Fix Image's logical flow which disposes its image too early, causing errors such as "Cannot clone a disposed image" (#110131)
parent 0f17bfdd
......@@ -1173,7 +1173,8 @@ class _ImageState extends State<Image> with WidgetsBindingObserver {
}
void _replaceImage({required ImageInfo? info}) {
_imageInfo?.dispose();
final ImageInfo? oldImageInfo = _imageInfo;
SchedulerBinding.instance.addPostFrameCallback((_) => oldImageInfo?.dispose());
_imageInfo = info;
}
......
......@@ -35,6 +35,53 @@ void main() {
imageCache.maximumSize = originalCacheSize;
});
testWidgets('Verify Image does not use disposed handles', (WidgetTester tester) async {
final ui.Image image100x100 = (await tester.runAsync(() async => createTestImage(width: 100, height: 100)))!;
final _TestImageProvider imageProvider1 = _TestImageProvider();
final _TestImageProvider imageProvider2 = _TestImageProvider();
final ValueNotifier<_TestImageProvider> imageListenable = ValueNotifier<_TestImageProvider>(imageProvider1);
final ValueNotifier<int> innerListenable = ValueNotifier<int>(0);
bool imageLoaded = false;
await tester.pumpWidget(ValueListenableBuilder<_TestImageProvider>(
valueListenable: imageListenable,
builder: (BuildContext context, _TestImageProvider image, Widget? child) => Image(
image: image,
frameBuilder: (BuildContext context, Widget child, int? frame, bool wasSynchronouslyLoaded) {
if (frame == 0) {
imageLoaded = true;
}
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) => ValueListenableBuilder<int>(
valueListenable: innerListenable,
builder: (BuildContext context, int value, Widget? valueListenableChild) => KeyedSubtree(
key: UniqueKey(),
child: child,
),
),
);
},
),
));
imageLoaded = false;
imageProvider1.complete(image10x10);
await tester.idle();
await tester.pump();
expect(imageLoaded, true);
imageLoaded = false;
imageListenable.value = imageProvider2;
innerListenable.value += 1;
imageProvider2.complete(image100x100);
await tester.idle();
await tester.pump();
expect(imageLoaded, true);
});
testWidgets('Verify Image resets its RenderImage when changing providers', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final _TestImageProvider imageProvider1 = _TestImageProvider();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment