使用
组件CachedNetworkImage可以支持直接使用或者通过ImageProvider。
引入依赖
1  | dependencies:  | 
执行flutter pub get,项目中使用
Import it
1  | import 'package:cached_network_image/cached_network_image.dart';  | 
添加占位图
1  | CachedNetworkImage(  | 
进度条展示
1  | CachedNetworkImage(  | 
原生组件Image配合
1  | Image(image: CachedNetworkImageProvider(url))  | 
使用占位图并提供provider给其他组件使用
1  | CachedNetworkImage(  | 
这样就可以加载网络图片了,而且,图片加载完成时,就被缓存到本地了,首先看下图片的加载流程
官网说了,它现在不包含缓存,缓存功能实际上是另一个库
flutter_cache_manager中实现的
原理
加载&显示
这里我们仅梳理图片加载和缓存的主流程,对于一些其他分支流程,或无关参数不做过多分析
首先,页面上使用的构造函数接收了一个必传参数imageUrl,用于生成ImageProvider提供图片加载
1  | class CachedNetworkImage extends StatelessWidget{  | 
这里可以看到,构造函数初始化了一个本地变量_image 类型是CachedNetworkImageProvider,它继承ImageProvider提供图片加载,看下它的构造函数
1  | /// 提供网络图片加载Provider并缓存  | 
它的构造函数调用了image_provider.CachedNetworkImageProvider的实例在_image_provider_io.dart中是加载的具体实现类
1  | /// IO implementation of the CachedNetworkImageProvider; the ImageProvider to  | 
这里的load方法即是图片加载的启动入口,它会在页面可见时被调用
它返回了一个MultiImageStreamCompleter传入_loadAsync,看下这个方法
1  | /// 异步加载  | 
这里我们看到了默认缓存管理器cacheManager创建的地方,为DefaultCacheManager,那么它如何缓存的呢,后边再分析。
下载的逻辑也是放在了ImageCacheManager下了,返回结果是一个stream完成多图下载的支持,下载完成通过yield 返回给ui解码最终显示。
1  | MultiImageStreamCompleter`支持多图加载继承自`ImageStreamCompleter  | 
这里做了显示逻辑,和最终转化成flutter上帧的处理,_scheduleAppFrame完成发送帧的处理
下载&缓存
上边的mngr调用了ImageCacheManager中的getImageFile方法现在就到了flutter_cache_manager这个三方库当中,它是被隐式依赖的,文件是image_cache_manager.dart
1  | mixin ImageCacheManager on BaseCacheManager {  | 
缓存判断逻辑在CacheStore提供两级缓存
1  | class CacheStore {  | 
_cacheInfoRepository缓存仓库是CacheObjectProvider使用的数据库缓存对象
1  | class CacheObjectProvider extends CacheInfoRepository  | 
可见数据库缓存的是CacheObject对象,保存了url、key、relativePath等信息
1  | class CacheObject {  | 
没有缓存下调用了_webHelper.downloadFile方法
1  | class WebHelper {  | 
总结
cached_network_image图片加载流程依赖ImageProvider,缓存和下载逻辑放在另一个库flutter_cache_manager下载文件在WebHelper中提供队列管理,依赖传入FileService做具体获取文件方便扩展默认实现HttpFileService,下载完成后路径保存在CacheObject保存在sqflite数据库