重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
FadeInImage官方默认只支持缓存到内存中,在项目中一般都需要把图片缓存到本地文件中
成都创新互联专注于定南网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供定南营销型网站建设,定南网站制作、定南网页设计、定南网站官网定制、小程序制作服务,打造定南网络公司原创品牌,更为您提供定南网站排名全网营销落地服务。
通过观察 FadeInImage 的构造函数中,得知 image 是调用 ResizeImage.resizeIfNeeded(imageCacheWidth, imageCacheHeight, NetworkImage(image, scale: imageScale)) 这个方法来获得图片的,而获得 ImageProvider 又是通过 NetworkImage(image, scale: imageScale)
继续跟进发现 NetworkImage 是继承 ImageProvider 的一个抽象类,里面有个工厂构造函数
通过修改这里的源码来实现本地缓存图片
在这之前需要先导入
其中,参数 image 类型为抽象类 ImageProvider ,定义了图片数据获取和加载的相关接口。
根据不同的数据来源,派生出不同的 ImageProvider :
抽象类 ImageProvider 提供了一个用于加载数据源的抽象方法 @protected ImageStreamCompleter load(T key, DecoderCallback decode); 接口,不同的数据源定义各自的实现。
子类 NetworkImage 实现如下:
load 方法返回类型为抽象类 ImageStreamCompleter ,其中定义了一些管理图片加载过程的接口,比如 addListener 、 removeListener 、 addOnLastListenerRemovedCallback 等, MultiFrameImageStreamCompleter 为其子类。
MultiFrameImageStreamCompleter 第一个参数 codec 类型为 Futureui.Codec ,用来对突破进行解码,当 codec 准备好的时候,就会立即对图片第一帧进行解码操作。
codec 为 _loadAsync 方法返回值,
_loadAsync 方法实现:
decode 方法的类型:
其中解码传入的回调方法 image_provider.DecoderCallback decode ,
传入 Uint8List ,返回 Futureui.Codec 。
而对 decode 回调方法的具体定义,在 ImageProvider 的 resolveStreamForKey 方法中做了定义, resolveStreamForKey 方法在 ImageProvider 的 resolve 方法中有调用, resolve 方法则为 ImageProvider 类层级结构的公共入口点。
resolveStreamForKey 和 resolve 实现如下:
decode 方法,即 PaintingBinding.instance!.instantiateImageCodec ,即为具体图片解码的方法实现。
ui.instantiateImageCodec 实现:
descriptor.instantiateCodec 方法实现:
_instantiateCodec 方法的实现,最终到了 native 的实现:
其中返回值类型 Codec 里定义了一些属性:
obtainKey 方法:
ImageProvider 定义了一个抽象方法 FutureT obtainKey(ImageConfiguration configuration); ,供子类来实现,其中 NetworkImage 的实现为:
obtainKey 作用:
配合实现图片缓存, ImageProvider 从数据源加载完数据后,会在 ImageCache 中缓存图片数据,图片数据缓存时一个 Map ,其中 Map 中的 key 便是 obtainKey 。
resolve 作为 ImageProvider 提供给 Image 的主入口方法,参数为 ImageConfiguration ,
resolve 其中调用了 _createErrorHandlerAndKey 方法,设置了成功回调和失败回调:
其中 _createErrorHandlerAndKey 方法的实现,便调用了 obtainKey 来设置 key 。
在成功回调里,调用了方法 resolveStreamForKey ,里面有具体的缓存实现 PaintingBinding.instance!.imageCache!.putIfAbsent :
PaintingBinding.instance!.imageCache 是ImageCache的一个实例,是 PaintingBinding 的一个属性,是一个单例,图片缓存是全局的。
如上述判断:
ImageCache 定义:
ImageCache 缓存池:
在 NetworkImage 中,对 ImageProvider 的抽象方法 obtainKey 进行了实现,将自己创建了一个同步 Future 进行返回:
同时,自身又重写了 ImageProvider 定义的 == 比较操作符,通过图片 url 和图片的缩放比例 scale 进行比较:
通过ImageCache提供的方法来设置:
一. flutter中我们想加载本地图片,需要两步:
二. flutter项目中本地图片加载的原理
在加载图片时,系统自动会根据屏幕分辨率优先选择到符合自己分配率的文件夹(2.0x或者3.0x或者4.0x)下去取相对应的图片,如果当前文件夹下没有,则会到低一倍的文件夹下去,如果还没有,则继续向更低一倍去取。(比如:iOS 5.5英寸及以上屏幕会优先选择去3.0x下去取图片,如果3.0x不存在或者3.0x文件夹下没有,则去2.0x下取;如果2.0x不存在或者2.0x下没有,则去1.0x下取;1.0x下再没有,则在images文件下取)。