Skip to content

Commit 37de496

Browse files
authored
Remove listeners from pending images when clearing cache (#107276)
1 parent 742a1c3 commit 37de496

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

packages/flutter/lib/src/painting/image_cache.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ class ImageCache {
195195
image.dispose();
196196
}
197197
_cache.clear();
198+
for (final _PendingImage pendingImage in _pendingImages.values) {
199+
pendingImage.removeListener();
200+
}
198201
_pendingImages.clear();
199202
_currentSizeBytes = 0;
200203
}

packages/flutter/test/painting/image_cache_test.dart

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ void main() {
179179
return completer1;
180180
})! as TestImageStreamCompleter;
181181

182+
// Make the image seem live.
183+
final ImageStreamListener listener = ImageStreamListener((_, __) {});
184+
completer1.addListener(listener);
185+
182186
expect(imageCache.statusForKey(testImage).pending, true);
183187
expect(imageCache.statusForKey(testImage).live, true);
184188
imageCache.clear();
@@ -346,10 +350,10 @@ void main() {
346350

347351
imageCache.clear();
348352
expect(imageCache.statusForKey(testImage1).pending, false);
349-
expect(imageCache.statusForKey(testImage1).live, true);
353+
expect(imageCache.statusForKey(testImage1).live, false);
350354

351355
completer1.testSetImage(testImage1);
352-
expect(imageCache.statusForKey(testImage1).keepAlive, true);
356+
expect(imageCache.statusForKey(testImage1).keepAlive, false);
353357
expect(imageCache.statusForKey(testImage1).live, false);
354358

355359
imageCache.putIfAbsent(testImage2, () => completer2);
@@ -602,4 +606,27 @@ void main() {
602606
imageInfo.dispose();
603607
expect(testImage.debugGetOpenHandleStackTraces()!.length, 0);
604608
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/87442
609+
610+
test('clear does not leave pending images stuck', () async {
611+
final ui.Image testImage = await createTestImage(width: 8, height: 8);
612+
613+
final TestImageStreamCompleter completer1 = TestImageStreamCompleter();
614+
615+
imageCache.putIfAbsent(testImage, () {
616+
return completer1;
617+
});
618+
619+
expect(imageCache.statusForKey(testImage).pending, true);
620+
expect(imageCache.statusForKey(testImage).live, true);
621+
expect(imageCache.statusForKey(testImage).keepAlive, false);
622+
623+
imageCache.clear();
624+
625+
// No one else is listening to the completer. It should not be considered
626+
// live anymore.
627+
628+
expect(imageCache.statusForKey(testImage).pending, false);
629+
expect(imageCache.statusForKey(testImage).live, false);
630+
expect(imageCache.statusForKey(testImage).keepAlive, false);
631+
});
605632
}

0 commit comments

Comments
 (0)