当前位置: 首页 > news >正文

Android内存优化之图片内存优化

本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点

图片相关的内存优化

图片相关的优化主要涉及几个方面:分辨率的适配、图片的压缩、图片的缓存

分辨率的适配

分辨率的适配主是针对我们放在drawable目录下的图片资源,目录和对应的手机分辨率可以看下图

所以我们需要不同分辨率的图片来放在对应的目录下来做适配,否则Android系统可能会将我们的图片拉伸导致变形。

图片的压缩

图片的压缩是指我们需要根据View所实际需要的图片尺寸来加载对应大小的图片。一般我们用的图片加载第三方库,比如Glide,都已经帮我们做了处理。所以这里的图片压缩我们只需要在我们自己处理图片的时候需要考虑。

图片压缩说起来也不复杂,主要是用到了BitmapFactory的Options,一般都分为如下几个步骤:

(1)先把inJustDecodeBounds设置为true,以便后面回去图片的实际大小

//先把inJustDecodeBounds设置为true,以便后面回去图片的实际大小
BitmapFactory.Options options = new BitmapFactory.Options();
//先解析图片的宽高信息,inJustDecodeBounds为true就只会加载图片的尺寸信息
options.inJustDecodeBounds = true;

复制代码

(2)然后压缩图片

//Resources res, int resId
BitmapFactory.decodeResource(res, resId, options);
复制代码

(3)计算压缩的比例,inSampleSize参数表示采样,会对图片的宽高进行缩放

//这里reqWidth和reqHeight表示实际需要的宽高
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int sampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        while ((halfHeight / sampleSize) >= reqHeight && (halfWidth / sampleSize) >= reqWidth) {
            sampleSize *= 2;
        }
    }

    return sampleSize;
}

//设置inSampleSize参数
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
复制代码

(4)将inJustDecodeBounds设置为false,加载图片数据

options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
复制代码

完整代码:

public static Bitmap decodeBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {

    BitmapFactory.Options options = new BitmapFactory.Options();
    //先解析图片的宽高信息
    options.inJustDecodeBounds = true;

    BitmapFactory.decodeResource(res, resId, options);

    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    //加载压缩后的图片
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);

}
复制代码

图片的缓存

同样的,一般我们加载图片都用的是第三方库,比如著名的Glide,图片缓存的事儿它已经帮我们做得很好了,所以我们不需要考虑缓存的事儿。但是我们还是要大致了解怎么样实现一个图片的缓存功能,以便不时之需。

实现缓存的话常用的就是LRU算法,具体的可以查看LinkedHashMap的源码分析和Glide的内存缓存思路。

这里简单介绍下Glide的内存缓存思路。内存缓存的作用就是对于内存中已经加载的图片避免重复加载。

(1)首先Glide内存缓存采用了2种策略,弱引用缓存和LRU算法内存缓存

(2)弱引用缓存就是把图片的弱引用缓存在一个HashMap中,被下载使用的图片首先会缓存在这个弱引用HashMap中。Glide会通过引用计数的方式来记录图片被引用的次数,当引用次数为0时,也就意味着图片资源不再被使用嘛,这时就会将图片资源从这个弱引用缓存中移除,并把这个图片资源加入到LRU算法内存缓存中

(3)LRU算法内存缓存的原理就是将图片资源用强引用的方式存储在LinkedHashMap中,当达到容量限制时移除最近最少使用的资源。Glide会在LRU缓存中的图片被重新使用时将图片资源从LRU缓存中删除,并添加到弱引用的缓存中去。这样做的原因就是防止图片被LRU算法缓存回收。


                      欢迎关注我的微信公众号,和我一起每天进步一点点!
复制代码

相关文章:

  • 重构到更深层的模型
  • 初识python: flush 实现进度条打印
  • es6 方法具名参数及默认值
  • 【大数据安全】Apache Kylin 安全配置(Kerberos)
  • mysql报错sql injection violation, syntax error: syntax error, expect RPAREN, actual IDENTIFIER
  • 聊聊redis的数据结构的应用
  • 利用POI和反射实现Excel自动识别实体类导入
  • 随谈10年的技术生涯和技术成长(转)
  • 以太坊开发环境
  • 8.Kafka offset机制
  • Webview独立进程并通过AIDL实现数据通信
  • axios执行原理了解一下!
  • MySQL语句执行分析(二)
  • 大数据争论:批处理与流处理的C位之战
  • 汉诺(hanio)塔问题
  • JavaScript-如何实现克隆(clone)函数
  • 230. Kth Smallest Element in a BST
  • Akka系列(七):Actor持久化之Akka persistence
  • AngularJS指令开发(1)——参数详解
  • crontab执行失败的多种原因
  • emacs初体验
  • IDEA 插件开发入门教程
  • javascript 总结(常用工具类的封装)
  • Laravel核心解读--Facades
  • MySQL-事务管理(基础)
  • ng6--错误信息小结(持续更新)
  • Terraform入门 - 1. 安装Terraform
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 聊聊sentinel的DegradeSlot
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 微信开源mars源码分析1—上层samples分析
  • Java数据解析之JSON
  • 正则表达式-基础知识Review
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • #14vue3生成表单并跳转到外部地址的方式
  • #if #elif #endif
  • #include<初见C语言之指针(5)>
  • $ is not function   和JQUERY 命名 冲突的解说 Jquer问题 (
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转)程序员疫苗:代码注入