Android经典面试题之图片Bitmap怎么做优化

简介: 本文介绍了图片相关的内存优化方法,包括分辨率适配、图片压缩与缓存。文中详细讲解了如何根据不同分辨率放置图片资源,避免图片拉伸变形;并通过示例代码展示了使用`BitmapFactory.Options`进行图片压缩的具体步骤。此外,还介绍了Glide等第三方库如何利用LRU算法实现高效图片缓存。

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

图片相关的内存优化

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

分辨率的适配

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

DPI、分辨率和drawable目录

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

或者直接使用svg图也是一个很好的选项。

图片的压缩

图片的压缩是指我们需要根据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算法缓存回收。

核心就是思考使用图片的每一个环节,用最低的开销来满足功能需求


欢迎关注我的公众号AntDream查看更多精彩文章!

目录
相关文章
|
17天前
|
XML Android开发 数据格式
Android利用selector(选择器)实现图片动态点击效果
本文介绍了Android中ImageView的`src`与`background`属性的区别及应用,重点讲解如何通过设置背景选择器实现图片点击动态效果。`src`用于显示原图大小,不拉伸;`background`可随组件尺寸拉伸。通过创建`selector_setting.xml`,结合`setting_press.xml`和`setting_normal.xml`定义按下和正常状态的背景样式,提升用户体验。示例代码展示了具体实现步骤,包括XML配置和形状定义。
Android利用selector(选择器)实现图片动态点击效果
|
1月前
|
存储 SQL 关系型数据库
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
|
18天前
|
Java Android开发
Android图片的手动放大缩小
本文介绍了通过缩放因子实现图片放大缩小的功能,效果如动图所示。关键步骤包括:1) 在布局文件中设置 `android:scaleType="matrix"`;2) 实例化控件并用 `ScaleGestureDetector` 处理缩放手势;3) 使用 `Matrix` 对图片进行缩放处理。为避免内存崩溃,可在全局配置添加 `android:largeHeap="true"`。代码中定义了 `beforeScale` 和 `nowScale` 变量控制缩放范围,确保流畅体验。
|
18天前
|
缓存 编解码 Android开发
Android内存优化之图片优化
本文主要探讨Android开发中的图片优化问题,包括图片优化的重要性、OOM错误的成因及解决方法、Android支持的图片格式及其特点。同时介绍了图片储存优化的三种方式:尺寸优化、质量压缩和内存重用,并详细讲解了相关的实现方法与属性。此外,还分析了图片加载优化策略,如异步加载、缓存机制、懒加载等,并结合多级缓存流程提升性能。最后对比了几大主流图片加载框架(Universal ImageLoader、Picasso、Glide、Fresco)的特点与适用场景,重点推荐Fresco在处理大图、动图时的优异表现。这些内容为开发者提供了全面的图片优化解决方案。
|
3月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
529 76
|
2月前
|
人工智能 算法 数据库
美团面试:LLM大模型存在哪些问题?RAG 优化有哪些方法?_
美团面试:LLM大模型存在哪些问题?RAG 优化有哪些方法?_
|
3月前
|
机器学习/深度学习 人工智能 JSON
Resume Matcher:增加面试机会!开源AI简历优化工具,一键解析简历和职位描述并优化
Resume Matcher 是一款开源AI简历优化工具,通过解析简历和职位描述,提取关键词并计算文本相似性,帮助求职者优化简历内容,提升通过自动化筛选系统(ATS)的概率,增加面试机会。
256 18
Resume Matcher:增加面试机会!开源AI简历优化工具,一键解析简历和职位描述并优化
|
5月前
|
编译器 Android开发 开发者
Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
Lambda表达式和匿名函数都是Kotlin中强大的特性,帮助开发者编写简洁而高效的代码。理解它们的区别和适用场景,有助于选择最合适的方式来解决问题。希望本文的详细讲解和示例能够帮助你在Kotlin开发中更好地运用这些特性。
85 9
|
6月前
|
并行计算 算法 安全
面试必问的多线程优化技巧与实战
多线程编程是现代软件开发中不可或缺的一部分,特别是在处理高并发场景和优化程序性能时。作为Java开发者,掌握多线程优化技巧不仅能够提升程序的执行效率,还能在面试中脱颖而出。本文将从多线程基础、线程与进程的区别、多线程的优势出发,深入探讨如何避免死锁与竞态条件、线程间的通信机制、线程池的使用优势、线程优化算法与数据结构的选择,以及硬件加速技术。通过多个Java示例,我们将揭示这些技术的底层原理与实现方法。
273 3
|
7月前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?