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;
AI 代码解读

(2)然后压缩图片

//Resources res, int resId
BitmapFactory.decodeResource(res, resId, options);
AI 代码解读

(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);
AI 代码解读

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

options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
AI 代码解读

完整代码:

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);

}
AI 代码解读

图片的缓存

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

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

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

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

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

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

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


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

目录
打赏
0
18
20
0
148
分享
相关文章
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
316 76
Resume Matcher:增加面试机会!开源AI简历优化工具,一键解析简历和职位描述并优化
Resume Matcher 是一款开源AI简历优化工具,通过解析简历和职位描述,提取关键词并计算文本相似性,帮助求职者优化简历内容,提升通过自动化筛选系统(ATS)的概率,增加面试机会。
165 18
Resume Matcher:增加面试机会!开源AI简历优化工具,一键解析简历和职位描述并优化
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
MySQL慢查询优化、索引优化,是必知必备,大厂面试高频,本文深入详解,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
Lambda表达式和匿名函数都是Kotlin中强大的特性,帮助开发者编写简洁而高效的代码。理解它们的区别和适用场景,有助于选择最合适的方式来解决问题。希望本文的详细讲解和示例能够帮助你在Kotlin开发中更好地运用这些特性。
63 9
面试必问的多线程优化技巧与实战
多线程编程是现代软件开发中不可或缺的一部分,特别是在处理高并发场景和优化程序性能时。作为Java开发者,掌握多线程优化技巧不仅能够提升程序的执行效率,还能在面试中脱颖而出。本文将从多线程基础、线程与进程的区别、多线程的优势出发,深入探讨如何避免死锁与竞态条件、线程间的通信机制、线程池的使用优势、线程优化算法与数据结构的选择,以及硬件加速技术。通过多个Java示例,我们将揭示这些技术的底层原理与实现方法。
217 3
Android面试高频知识点(1) 图解Android事件分发机制
Android面试高频知识点(1) 图解Android事件分发机制
深入探索iOS与Android系统的差异性及优化策略
在当今数字化时代,移动操作系统的竞争尤为激烈,其中iOS和Android作为市场上的两大巨头,各自拥有庞大的用户基础和独特的技术特点。本文旨在通过对比分析iOS与Android的核心差异,探讨各自的优势与局限,并提出针对性的优化策略,以期为用户提供更优质的使用体验和为开发者提供有价值的参考。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等