Flutter图片加载原理与缓存

本文深入探讨了Flutter中图片加载的工作原理,重点解析了Image组件的缓存机制。通过ImageConfiguration获取设备相关信息,并利用ImageCache管理全局图片缓存。缓存管理包括缓存上限设置、清理策略等,确保高效利用内存。同时,文章介绍了如何自定义缓存上限,并分析了网络图片的唯一标识key的生成逻辑。最后,通过源码分析,展示了如何构建一个简单的Image组件模拟实现,强调了图片数据流的监听和重建过程。
摘要由CSDN通过智能技术生成

}
key.then((T key) {
obtainedKey = key;
// 缓存的处理逻辑在这里,记为A,下面详细介绍
final ImageStreamCompleter completer = PaintingBinding.instance
.imageCache.putIfAbsent(key, () => load(key), onError: handleError);
if (completer != null) {
stream.setCompleter(completer);
}
}).catchError(handleError);
});
return stream;
}

ImageConfiguration 包含图片和设备的相关信息,如图片的大小、所在的AssetBundle(只有打到安装包的图片存在)以及当前的设备平台、devicePixelRatio(设备像素比等)。Flutter SDK提供了一个便捷函数createLocalImageConfiguration来创建ImageConfiguration 对象:

ImageConfiguration createLocalImageConfiguration(BuildContext context, { Size size }) {
return ImageConfiguration(
bundle: DefaultAssetBundle.of(context),
devicePixelRatio: MediaQuery.of(context, nullOk: true)?.devicePixelRatio ?? 1.0,
locale: Localizations.localeOf(context, nullOk: true),
textDirection: Directionality.of(context),
size: size,
platform: defaultTargetPlatform,
);
}

我们可以发现这些信息基本都是通过Context来获取。

上面代码A处就是处理缓存的主要代码,这里的PaintingBinding.instance.imageCache 是 ImageCache的一个实例,它是PaintingBinding的一个属性,而Flutter框架中的PaintingBinding.instance是一个单例,imageCache事实上也是一个单例,也就是说图片缓存是全局的,统一由PaintingBinding.instance.imageCache 来管理。

下面我们看看ImageCache类定义:

const int _kDefaultSize = 1000;
const int _kDefaultSizeBytes = 100 << 20; // 100 MiB

class ImageCache {
// 正在加载中的图片队列
final Map<Object, _PendingImage> _pendingImages = <Object, _PendingImage>{};
// 缓存队列
final Map<Object, _CachedImage> _cache = <Object, _CachedImage>{};

// 缓存数量上限(1000)
int _maximumSize = _kDefaultSize;
// 缓存容量上限 (100 MB)
int _maximumSizeBytes = _kDefaultSizeBytes;

// 缓存上限设置的setter
set maximumSize(int value) {…}
set maximumSizeBytes(int value) {…}

… // 省略部分定义

// 清除所有缓存
void clear() {
// …省略具体实现代码
}

// 清除指定key对应的图片缓存
bool evict(Object key) {
// …省略具体实现代码
}

ImageStreamCompleter putIfAbsent(Object key, ImageStreamCompleter loader(), { ImageErrorListener onError }) {
assert(key != null);
assert(loader != null);
ImageStreamCompleter result = _pendingImages[key]?.completer;
// 图片还未加载成功,直接返回
if (result != null)
return result;

// 有缓存,继续往下走
// 先移除缓存,后再添

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值