Flutter图片缓存管理ImageCache原理分析

目录
  • 引言
  • PaintingBinding
    • 减少图片缓存
    • 增大阀值
  • 思考

引言

设计: 嗯? 这个图片点击跳转进详情再返回图片怎么变白闪一下呢?
产品: 是啊是啊! 一定是个bug
开发: 囧囧囧

在开发过程中, 也许你也遇到过这样一个场景. 进入一个页面后,前一个页面的图片都会闪白一下. 或者在列表中,加载很多列表项后,之前列表中的图片都需要重新加载.你有没有想过这一切的原因是什么呢?

没错! 它就是我们今天介绍的主人公 --- ImageCache

可能有些人对ImageCache还有些陌生, 我们在之前的章节有说过启动流程时Flutter runApp到渲染上屏,有介绍过其中PaintingBinding这个mixin类.带着探索的心我们先去看看PaintingBinding都做了 一些什么操作呢?

PaintingBinding

PaintingBinding在构造函数中,除了构建自身的实例.同时也构建了图片缓存的管理实例.也包括了着色器预热.

{
    _instance = this;
    // 创建了图片缓存管理
    _imageCache = createImageCache();
    shaderWarmUp?.execute();
}

着色器预热可能大部分人都没有接触过,我们只需要知道通过着色器预热,可以提高首次编译的速度即可.有兴趣可以看一下这篇文章着色器预热; 我们现在把目光重新聚焦到今天的主题, 也就是createImageCache()这里.可以看到它直接返回了一个ImageCache的对象. 这里我们暂且不谈ImageCache, 再去看看在PaintingBinding有没有和ImageCache相关的一些代码吧.

  @override
  void evict(String asset) {
    // 调用了rootBundle.evict(asset);
    // 也就是从缓存中移除这个key的资源
    super.evict(asset);
    // 清除所有已显示和不再用到的图片缓存
    imageCache.clear();
    // 清除所有实时引用的图片缓存
    imageCache.clearLiveImages();
  }

  @override
  void handleMemoryPressure() {
    // rootBundle.clear();
    // 当操作系统通知应用程序内存压力情况时调用。
    // 清除所有的图片资源
    super.handleMemoryPressure();
    imageCache.clear();
  }

可以看到, 基本上所有的引用都避不开内存问题. 也就是文章开头出现的bug. 那么,为什么会出现闪白呢? 有多种可能,有可能是系统感受到了内存压力调用了handleMemoryPressure() 方法,清除了图片缓存,或者在ImageCache中,达到了最大缓存,因此内部根据least-recently-used的原则回收了图片缓存.所以回头再看的时候,图片又重新加载了一遍.自然发生了闪白现象. 既然知道了原因,那么解决问题的方法:

  • 减少图片缓存
  • 增大图片缓存的阀值,让系统感觉到压力的阀值提升 我们来分别分析一下两者的可行性

减少图片缓存

如果要减少图片缓存, 我们要知道图片的内存是怎么计算的? 图片内存=分辨率*每个像素点大小 减少的方法也就出来了:

  • 减少分辨率
    也就是降低采样率.flutter中即cacheHeight和cacheWidth
  • 减少像素点大小
    这里也就是像素点的格式,ALPHA_8、RGB_565、ARGB_4444、ARGB_8888、RGBA_F16这些

增大阀值

这里需要去看一下ImageCache中.我们推断一下,什么情况下一个缓存池会达到阀值呢? 那一定是有新图片插入,所以总量才会提升才会够到阀值的门槛.我们找一下有没有相关的方法. 嗯哼~ 果然有一个_checkCacheSize

{
    ...
    // 只要当前的内存超标就会一直执行下去
    while (_currentSizeBytes > _maximumSizeBytes || _cache.length > _maximumSize) {
      // 根据least-recently-used这个逻辑去依次清除图片缓存
      final Object key = _cache.keys.first;
      final _CachedImage image = _cache[key]!;
      _currentSizeBytes -= image.sizeBytes!;
      image.dispose();
      _cache.remove(key);
    }
    ...
}

说明我们阀值取决于_maximumSizeBytes和_maximumSize, 一个负责最大缓存图片内存,一个负责最大缓存图片数. 也就是说我们更新这两个指就可以改变图片内存的阀值.从而减少内存回收的频率.

思考

很多问题的发生实际上源码中都有些提示, 带着问题去看收获的远远比单独阅读源码要有收获的多.
这里是weniner,一个在奋斗的flutter. 有些收获的话,不妨点个关注哦!

以上就是Flutter图片缓存管理ImageCache原理分析的详细内容,更多关于Flutter ImageCache的资料请关注我们其它相关文章!

(0)

相关推荐

  • Flutter TV Android端开发技巧详细教程

    目录 前言 开发思路 先上效果 开发细节 使用RawKeyboardListener Provider层对事件进行处理 注意 总结 文件参考 TV keyCode详解 前言 最近公司有了新的业务,把现有Flutter Android项目应用到TV上去,这不,Asscre的活就来了. 本文详细说明Flutter for TV的两种实现方式,能力有限,不足之处欢迎指点,哈哈哈 开发思路 在开发之前,我们先设定一下我们的思路. 即,如何对原有程序代码侵入式最小.性能最佳.可玩性更高做出设定. 那么,通

  • Flutter开发技巧ListView去除水波纹方法示例

    正文 ScrollConfiguration( behavior: NoScrollBehaviorWidget(), child: ListView( ...... ...... ), ), 调用ScrollConfiguration官方类,实现behavior NoScrollBehaviorWidget用于去除水波纹的自定义Widget import 'package:flutter/material.dart'; /// 去除listview水印 /// ScrollConfigurat

  • Flutter图片加载与缓存机制的深入探究

    目录 前言 图片控件 图片解析 缓存管理 ​新增缓存 缓存清理 图片加载 滑动中处理 总结 前言 今天来学习一下 Flutter 自身是如何加载图片和管理图片的. Flutter 提供了一个图片控件 Image,Image 定义了若干中加载图片的方式,包括 Image.asset.Image.file.Image.network.Image.memory. Image内部维护了一个 ImageProvider对象,ImageProvider则真正维护整个图片加载的工作.Widget 本身内部是体

  • Flutter中网络图片加载和缓存的实现

    前言 应用开发中经常会碰到网络图片的加载,通常我们会对图片进行缓存,以便下次加载同一张图片时不用再重新下载,在包含有大量图片的应用中,会大幅提高图片展现速度.提升用户体验且为用户节省流量.Flutter本身提供的Image Widget已经实现了加载网络图片的功能,且具备内存缓存的机制,接下来一起看一下Image的网络图片加载的实现. 重温小部件Image 常用小部件Image中实现了几种构造函数,已经足够我们日常开发中各种场景下创建Image对象使用了. 有参构造函数: Image(Key k

  • Flutter SystemChrome使用方法详解

    目录 引言 setPreferredOrientations 设置横屏或坚屏 setEnabledSystemUIMode 设置全屏显示 setSystemUIOverlayStyle 设置 overlay 样式, 全屏播放视频 setSystemUIChangeCallback AnnotatedRegion 引言 SystemChrome 控制操作系统图形界面的特定方面以及它如何与应用程序交互. 需要注意的是在使用的时候一定要保证先执行 WidgetsFlutterBinding.ensur

  • Flutter CustomPaint绘制widget使用示例

    目录 CustomPaint 介绍 使用 CustomPaint size 的大小. isComplex willChange foregroundPainter 动画 CustomPaint 介绍 Flutter CustomPaint 提供了一个 canvas,可以在绘制阶段在上面进行绘制内容. 需要绘制时,CustomPaint 首先要求它的 painter 在当前画布上绘画,然后它绘画它的 child,在绘画完它的 child 之后,要求他的 foregroundPainter 绘画.

  • Flutter最小刷新范围探索ValueListenableBuilder使用详解

    目录 引子 ValueListenableBuilder 如何用 怎么做 不足点 引子 管理对象太多? 刷新管理太麻烦 ? Flutter刷新范围控制不好 ? 不妨看看本文 , 希望提供给你一些思路吧 ! 说起 Flutter 刷新, 你的第一印象是什么 ? setState ? 是的, 只要使用过 Flutter 的人, 第一印象都必然是 setState , 但是由于 setState 滥用的问题, 性能问题就脱颖而出. 因此产出了诸如 Fish_redux 之流, 这些框架尽可能的使用 S

  • Flutter RendererBinding作用源码分析

    目录 分析 PipelineOwner flushLayout flushCompositingBits flushPaint flushSemantics initRenderView scheduleInitialLayout scheduleInitialPaint 分析 RendererBinding 的作用是负责render tree 和flutter engine之间的连接. 我们在启动App的时候,首先会创建 PiplineOwner ,然后通过platformDispatcher

  • Flutter图片缓存管理ImageCache原理分析

    目录 引言 PaintingBinding 减少图片缓存 增大阀值 思考 引言 设计: 嗯? 这个图片点击跳转进详情再返回图片怎么变白闪一下呢?产品: 是啊是啊! 一定是个bug开发: 囧囧囧 在开发过程中, 也许你也遇到过这样一个场景. 进入一个页面后,前一个页面的图片都会闪白一下. 或者在列表中,加载很多列表项后,之前列表中的图片都需要重新加载.你有没有想过这一切的原因是什么呢? 没错! 它就是我们今天介绍的主人公 --- ImageCache 可能有些人对ImageCache还有些陌生,

  • jQuery实现图片走马灯效果的原理分析

    本文实例分析了jQuery实现图片走马灯效果的原理.分享给大家供大家参考,具体如下: 这里只讲解水平走马灯效果,垂直向上走马灯效果不讲解,原理一样,但是水平走马灯效果有一个小坑.待会讲解 先上代码: HTML: <div class="box"> <div style="width: 1000px;" id="boxdiv"> <ul> <li style="display: block;&qu

  • SpringBoot2 整合Ehcache组件,轻量级缓存管理的原理解析

    本文源码:GitHub·点这里 || GitEE·点这里 一.Ehcache缓存简介 1.基础简介 EhCache是一个纯Java的进程内缓存框架,具有快速.上手简单等特点,是Hibernate中默认的缓存提供方. 2.Hibernate缓存 Hibernate三级缓存机制简介: 一级缓存:基于Session级别分配一块缓存空间,缓存访问的对象信息.Session关闭后会自动清除缓存. 二级缓存:是SessionFactory对象缓存,可以被创建出的多个 Session 对象共享,二级缓存默认是

  • asp.net中利用ashx实现图片防盗链的原理分析

    直接分析盗链原理:看下面用httpwatch截获的http发送的数据 GET /Img.ashx?img=svn_work.gif HTTP/1.1 Accept: */* Referer: http://www.jb51.net/ Accept-Language: zh-cn UA-CPU: x86 Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET

  • flutter图片组件核心类源码解析

    目录 导语 问题 Image的核心类图及其关系 网络图片的加载过程 网络图片数据的回调和展示过程 补上图片内存缓存的源码分析 如何支持图片的磁盘缓存 总结 导语 在使用flutter 自带图片组件的过程中,大家有没有考虑过flutter是如何加载一张网络图片的? 以及对自带的图片组件我们可以做些什么优化? 问题 flutter 网络图片是怎么请求的? 图片请求成功后是这么展示的? gif的每一帧是怎么支持展示的? 如何支持图片的磁盘缓存? 接下来,让我们带着问题一起探究flutter 图片组件的

  • Android开发笔记之图片缓存、手势及OOM分析

    把图片缓存.手势及OOM三个主题放在一起,是因为在Android应用开发过程中,这三个问题经常是联系在一起的.首先,预览大图需要支持手势缩放,旋转,平移等操作:其次,图片在本地需要进行缓存,避免频繁访问网络:最后,图片(Bitmap)是Android中占用内存的大户,涉及高清大图等处理时,内存占用非常大,稍不谨慎,系统就会报OOM错误. 庆幸的是,这三个主题在Android开发中属于比较普遍的问题,有很多针对于此的通用的开源解决方案.因此,本文主要说明笔者在开发过程中用到的一些第三方开源库.主要

  • Android图片缓存原理、特性对比

    这是我在 MDCC 上分享的内容(略微改动),也是源码解析第一期发布时介绍的源码解析后续会慢慢做的事. 从总体设计和原理上对几个图片缓存进行对比,没用到他们的朋友也可以了解他们在某些特性上的实现. 一. 四大图片缓存基本信息 Universal ImageLoader 是很早开源的图片缓存,在早期被很多应用使用. Picasso 是 Square 开源的项目,且他的主导者是 JakeWharton,所以广为人知. Glide 是 Google 员工的开源项目,被一些 Google App 使用,

  • 深入分析iOS应用中对于图片缓存的管理和使用

    我们的 iOS 应用都包含了大量的图像.创建富有吸引力的视图,主要依赖于大量的装饰图片,所有这些首先必须从远程服务器获取.如果每次打开应用都要从服务器一次又一次的获取每个图像,那么用户体验肯定达不到好的效果,所以本地缓存远程图像是非常有必要的. 两种方式加载本地图片 1.通过imageNamed:方法加载图片 用过这种方式加载图片,一旦图片加载到内存中,那么就不会销毁,一直到程序退出.(也就是说imageNamed:会有图片缓存的功能,当下次访问图片的时候速度会更快.) 用这种方式加载图片,图片

  • C++ 内存管理原理分析

    1.C/C++中程序内存分布 C/C++中程序内存区域大致划分为:内核空间(这部分用户不能读写).栈.内存映射段.堆.数据段(存储全局数据.静态数据).代码段(存储可执行代码.只读常量,又称常量区). 1.1 内存分布图 1.2 小试牛刀 接下来看下如下代码,思考下每一个变量分别在哪个内存区域? int globalVar = 1; static int staticGlobalVar = 1; void test() { static int staticVar = 1; int localV

随机推荐