Flutter 10完整进化详解:深入图像加载流程
在Flutter中,图像加载主要由Image
控件和
Image
一定对应它的 ❀❀❀❀❀❀ layout 和 油漆,那么这个过程中图像是如何转换成屏幕并显示出来的呢? ? ,首先 Image
获取 ImageStream
对象 2 - Ima,然后 我_ImageState使用2 ImageStream 添加监控,等待图像数据
ImageProvider
使用loadloadload方法amgege对象
- 4。然后
ImageStream
绑定到 ImageStreamCompleter
- 5,然后通过
ImageStreamCompleter 然后 PaintingBinding 编码转换得到ui.Codec
绘图.对象并封装ImageInfo
返回回调ImageStream的显示,设置为_ImageState
结构 RawImage
来自对象。
- 7。最后,在
ImageInfo♽❀中用颜料绘制RawImage
/ RenderImage
。 ui.Codec
注意,这是 ui.Codec
以及后面的ui.Imageui.Image
等只是为了在导入时区分Flutter类型和其他类型而添加对象:将'dart:ui'作为UI表示编解码器;
你头晕了吗?放松!后面我们会慢慢了解这个过程。 ![Flutter完整开发实战详解十:深入图片加载流程]()
Flutter的图片加载过程主要有三个作用:
Image
:用于显示图片的Widget,最后绘制内部utin❝。 ? 、AssetImage
等以获取 ImageStream
用于跟踪 ❝❀ 结果。
ImageStream
:图片上传对象ImageStreamCompleter
最终返回ImageInfo和 geInfo
包含Render的图片
最后一个 绘制对象 ui.Image
。
如上整体镜像流程所示,网络镜像是通过这个Provider加载NetworkImage
。不同Provider的实现确实很大。大同小异,其中最重要的实现方法主要如下图所示:![Flutter完整开发实战详解十:深入图片加载流程]()
1。 getKey
该方法主要用于标记当前Provider
是否存在。例如,在 NetworkImage
中,返回的方法是 SynchronousFuture(this)♼,即❀♼,即,并且使用生成的密钥 ImageProvider
♼ 缓存键值为。 NetworkImage
主要是runtimeType
、
、l、 l scale
这三个参数定义了两个NetworkImage。等于 ,因此,除了url
之外,图像
的比例也会影响缓存的对象。 2。 load(T key)
load
方法,顾名思义就是加载,而这个方法中使用的key无疑是从上面的obtainKey
方法中获取到的。
load
方法返回ImageStreamCompleter
抽象对象,主要使用 ❀ dart:ui.Image 例如,NetworkImage。
是 MultiFrameImageStreamCompleter
的子类,可以处理多帧动画。如果图像中只有一针,则执行一次并完成。3。解决
ImageProvider
的关键在于resolve
方法。从流程图中我们知道该方法为 Image
生命周期调用方法中 didChangeDependencies
,
, ♻, te
reassemble
被调用。在下面的源代码中可以看到,这里调用了obtainKey
和load
![Flutter完整开发实战详解十:深入图片加载流程]()
这里有一个有趣的对象,那就是❝♶❝!
因为在Flutter中,同步异常可以用try-catch捕获,而像Future
这样的异步异常无法直接在当前try-catch中捕获。
所以在Dart的Zone
概念中,你可以给执行对象分配一个Zone
,这类似于沙箱环境,你可以在沙箱内部提供这个。 all 可以捕获、捕获或修改某些代码行为,例如所有未处理的异常。
resolve
方法主要使用PaintingBinding.instance.imageCache.putIfAbsent(key, () => load(key)
in 是一个胶水类,主要用在 WidgetsFlutterBinding. 通过 Mixins. 正如我们在上一章中所说, WidgetsFlutterBinding
是我们的启动方法❙
因此,图像缓存作为单个实例保留在 PaintingBinding.instance.imageCache 中。
如下图所示,putIfAbsent在方法内部,主要是在内存中进行评估。对象是否已经缓存或者已经缓存,如果是,则返回ImageStreamCompleter
,否则请致电loader
。值得注意的是,缓存目前有两种状态,因为返回的 ImageStreamCompleter
并不意味着图像已经加载完毕,所以如果是第一次加载, 会先出现。 I_PendingImage 用于指向 key 的图像处于 加载状态,并添加 Listener
。 ![Flutter完整开发实战详解十:深入图片加载流程]()
不对,这里的缓存概念和我们理解的有点不一样。之前,通常会缓存关键位图对象,也就是实际的绘图数据,而Flutter 只缓存 ImageStreamCompleter
对象,而不是实际的绘图对象 dart:ui.Image
。 ? dart:ui.Image
对象 ImageInfo。 接下来我们看 内部 那又怎么样?现在回顾一下一开始的流程图。是不是感觉一切都清楚了? 了解了上面的流程,我们知道Flutter实现了内存中图片缓存,但没有实现本地图片缓存,所以我们的出发点应该是从 根据上面对 _loadAsync方法加载的,所以我们加载 NetworkImage 简历 复制代码,编辑 结合 关于闲鱼 Flutter Web 应用内存分析文章详细分析了图片加载导致的内存问题,其中之一就是 我们知道上面的流程, 在Flutter中 所以简单粗暴的做法是:tingb.simage.inchem.inchem。 ; 在图像中,您可以通过 自此,第十章终于结束了! (///▽///) 作者:连毛德小果ImageStreamCompleter
实现类MultiFrameImageStreamCompleterMa。如下代码所示,
通过ImageInfo 对其进行封装,并逐渐回调回MultiFrameImageStreamCompleter
主要通过codec
参数获取渲染数据,该数据源是从_ssync获取的。 方法,主要通过http获取图像上传后,通过PaintingBinding
对图像数据进行编码,将图像转换为机器绘制的数据。MultiFrameImageStreamCompleter
、ui.Codec
来自_ImageState。 ,然后将数据传递给
RenderImage
- setState♽进行绘制。
同时页面出现时不暂停加载图片等。2。本地图片缓存
ImageProvider
开始。 NetworkImage
的分析,我们知道图片是通过http通过_loadAsync
_loadAsync
,支持加载前读取http本地缓存,加载后将数据存储在本地。 flutter_cache_manager
插件,如下代码所示,可以快速轻松地启用本地图片缓存: Future<ui.Codec> _loadAsync(NetworkImage key) async {
assert(key == this);
/// add this start
/// flutter_cache_manager DefaultCacheManager
final fileInfo = await DefaultCacheManager().getFileFromCache(key.url);
if(fileInfo != null && fileInfo.file != null) {
final Uint8List cacheBytes = await fileInfo.file.readAsBytes();
if (cacheBytes != null) {
return PaintingBinding.instance.instantiateImageCodec(cacheBytes);
}
}
/// add this end
final Uri resolved = Uri.base.resolve(key.url);
final HttpClientRequest request = await _httpClient.getUrl(resolved);
headers?.forEach((String name, String value) {
request.headers.add(name, value);
});
final HttpClientResponse response = await request.close();
if (response.statusCode != HttpStatus.ok)
throw Exception('HTTP request failed, statusCode: ${response?.statusCode}, $resolved');
final Uint8List bytes = await consolidateHttpClientResponseBytes(response);
if (bytes.lengthInBytes == 0)
throw Exception('NetworkImage is an empty file: $resolved');
/// add this start
await DefaultCacheManager().putFile(key.url, bytes);
/// add this edn
return PaintingBinding.instance.instantiateImageCodec(bytes);
}
复制代码
3.其他插件。缓存量
ImageCache
问题。 ImageCache
缓存了一个异步对象。缓存异步加载对象的一个问题是,在图像加载和解码之前你无法知道会消耗多少内存,并且大量图像的加载会导致解码任务产生大量 IO。 ImageCache
默认缓存大小为const int _kDefaultSize = 1000;
const int _kDefaultSizeBytes = 100 << 20; // 100
复制代码
2、.9 图像
centerSlice
设置参数设置 .9 图像效果。
链接:https://juejin.im/post/5cb1896ce51d456e63760449‽来源:♓❓❓‿s版权归作者所有。商业转载请联系作者获得许可。非商业转载请注明出处。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。