使用
组件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
数据库