After setting memCacheHeight, .evict() is invalid
code
CachedNetworkImage(
memCacheHeight: 200,
imageUrl:
'https://img0.baidu.com/it/u=3863723642,1799521238&fm=26&fmt=auto&gp=0.jpg');
ImageCache? imageCache = PaintingBinding.instance?.imageCache;
print(imageCache?.currentSize);
print(imageCache?.currentSizeBytes);
//-------------
CachedNetworkImageProvider(
"https://img0.baidu.com/it/u=3863723642,1799521238&fm=26&fmt=auto&gp=0.jpg",
).evict();
ImageCache? imageCache = PaintingBinding.instance?.imageCache;
print(imageCache?.currentSize);
print(imageCache?.currentSizeBytes);
error
The picture still exists in memory
version
cached_network_image: ^3.1.0 Flutter 2.2.3 • channel stable • https://github.com/flutter/flutter.git Framework • revision f4abaa0735 (9 weeks ago) • 2021-07-01 12:46:11 -0700 Engine • revision 241c87ad80 Tools • Dart 2.13.4
That's correct. You will get a different ImageProvider here. For example when you have large and small versions of the same image you might want to evict the large image all the time after it is no longer needed, but you can keep the small versions in memory.
Could you try:
CachedNetworkImage(
memCacheHeight: 200,
imageUrl:
'https://img0.baidu.com/it/u=3863723642,1799521238&fm=26&fmt=auto&gp=0.jpg');
CachedNetworkImage(
memCacheHeight: 200,
imageUrl:
'https://img0.baidu.com/it/u=3863723642,1799521238&fm=26&fmt=auto&gp=0.jpg',
).evict();
If that doesn't work please reopen the issue and I'll have a closer look.
I tried it,The only key of obtainKey has been used in the ResizeImage component to clean up the memory. Is there any way for CachedNetworkImage to obtain the obtainKey?
ResizeImage aa = ResizeImage(NetworkImage(imgUrl), width: 200);
aa.obtainKey(ImageConfiguration.empty).then((value) {
ImageCache? imageCache = PaintingBinding.instance?.imageCache;
imageCache?.evict(value);
});
Is there any way for CachedNetworkImage to obtain acquireKey?
Hmm of course, the ResizeImage is in between. I think the same trick should work as well:
ResizeImage aa = ResizeImage(CachedNetworkImageProvider(imgUrl), height: 200);
aa.obtainKey(ImageConfiguration.empty).then((value) {
ImageCache? imageCache = PaintingBinding.instance?.imageCache;
imageCache?.evict(value);
});
Thanks, I know how to deal with it
@maskletter @renefloor @bounty1342 I encountered the same problem and submitted a PR #676 which may not be very good. Please pay attention to it and give some suggestions. Thank you very much.
Hi @renefloor, I have close PR #676 because I think it a bug in ResizeImage. I rewrite ResizeImage for get ResizeImageKey. And I will add some code in error widget build to evict pending cache when something error. I don't know if this problem has better solution?
CachedNetworkImage(
memCacheHeight: null,
memCacheWidth: 375,
progressIndicatorBuilder: (context, url, progress) =>
Text("progress:${progress.progress}"),
errorWidget: (context, url, object) {
// follow #648 Proactively clear the pending cache
ResizeImage aa =
ResizeImage(CachedNetworkImageProvider(imgUrl), width: 375);
aa.obtainKey(ImageConfiguration.empty).then((value) {
ImageCache? imageCache = PaintingBinding.instance?.imageCache;
imageCache?.evict(value);
});
return Text("error");
},
imageUrl: imgUrl),
At one point, cacheNetwork image call octoImage wrap in a ResizeImage, it's where the imageprovider reference in lost. I'm on mobile now but can give source later today.
Hi @bounty1342, I have see that, I found it a bug in ResizeImage. If I use Image.network, it's also can't evict pending image cache, because the key is not right which flutter provider. In pending image cache, the key is ResizeImageKey, and it's private we can't get it. Only one way to get it by create a new ResizeImage.
// this code also has the same evict problem
Image(
image: ResizeImage(NetworkImage(imgUrl), width: 375),
),
I don't know if this problem has better solution?
@weiminghuaa I don't know either. I have to take some time to look into it, but I can imagine it not working due to the wrapping of the ResizeImage.
// this code also has the same evict problem
Image(
image: ResizeImage(NetworkImage(imgUrl), width: 375),
),
Can you evict this image by calling: ResizeImage(NetworkImage(imgUrl), width: 375).evict()?
Can you evict this image by calling: ResizeImage(NetworkImage(imgUrl), width: 375).evict()?
@renefloor Yes, it's ok.
So we can change this:
static Future evictFromCache(
String url, {
String? cacheKey,
BaseCacheManager? cacheManager,
double scale = 1.0,
}) async {
cacheManager = cacheManager ?? DefaultCacheManager();
await cacheManager.removeFile(cacheKey ?? url);
return CachedNetworkImageProvider(url, scale: scale).evict();
}
to this:
static Future evictFromCache(
String url, {
String? cacheKey,
int? memCacheWidth,
int? memCacheHeight,
BaseCacheManager? cacheManager,
double scale = 1.0,
}) async {
cacheManager = cacheManager ?? DefaultCacheManager();
await cacheManager.removeFile(cacheKey ?? url);
final imageProvider = ResizeImage.resizeIfNeeded(
memCacheWidth,
memCacheHeight,
CachedNetworkImageProvider(url, scale: scale),
);
return imageProvider.evict();
}
No, I tracked the source code and found a problem here. If network image load error when no network connect, can't evict the key. So next time it's can't retry load image even though nework is ok. Because the pending image cache not evict the image key.
Stream<ui.Codec> _loadAsync(
image_provider.CachedNetworkImageProvider key,
StreamController<ImageChunkEvent> chunkEvents,
DecoderCallback decode,
) {
assert(key == this);
return ImageLoader().loadAsync(
url,
cacheKey,
chunkEvents,
decode,
cacheManager ?? DefaultCacheManager(),
maxHeight,
maxWidth,
headers,
errorListener,
imageRenderMethodForWeb,
() => PaintingBinding.instance?.imageCache?.evict(key),
);
}
Ah you're talking about a failed image, that's interesting. The OP talked about evict in general, then my piece of code already helped.
It's a bit hacky, but I think this should work:
Stream<ui.Codec> _loadAsync(
image_provider.CachedNetworkImageProvider key,
StreamController<ImageChunkEvent> chunkEvents,
DecoderCallback decode,
) {
assert(key == this);
return ImageLoader().loadAsync(
url,
cacheKey,
chunkEvents,
decode,
cacheManager ?? DefaultCacheManager(),
maxHeight,
maxWidth,
headers,
errorListener,
imageRenderMethodForWeb,
() => PaintingBinding.instance?.imageCache?.evict(ResizeImage.resizeIfNeeded(
memCacheWidth,
memCacheHeight,
CachedNetworkImageProvider(url, cacheKey: cacheKey, scale: scale),
)),
);
}
Edit: nvm, we don't have that information here of course...
Yes,no memCacheWidth, memCacheHeight