Android性能优化之Bitmap的内存优化
2016-03-30 13:51
531 查看
1、BitmapFactory解析Bitmap的原理
BitmapFactory提供的解析Bitmap的静态工厂方法有以下五种:decodeFile和decodeResource其实最终都是调用decodeStream方法来解析Bitmap,decodeStream的内部则是调用两个native方法解析Bitmap的:
接下来就是看看这两个方法在解析Bitmap时究竟有什么区别decodeFile、decodeResource,查看后发现它们调用路径如下:
decodeFile->decodeStream
decodeResource->decodeResourceStream->decodeStream
decodeResource在解析时多调用了一个decodeResourceStream方法,而这个decodeResourceStream方法代码如下:
opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
对opts.inTargetDensity进行了赋值,该值为当前设备的densityDpi值,所以说在decodeResourceStream方法中主要做了两件事:
1、对opts.inDensity赋值,没有则赋默认值160
2、对opts.inTargetDensity赋值,没有则赋当前设备的densityDpi值
之后重点来了,之后参数将传入decodeStream方法,该方法中在调用native方法进行解析Bitmap后会调用这个方法setDensityFromOptions(bm, opts);:
所以总结来说,setDensityFromOptions方法就是把inTargetDensity的值赋给Bitmap,不过前提是opts.inScaled = true;
进过上面的分析,可以得出这样一个结论:
在不配置Options的情况下:
1、decodeFile、decodeStream在解析时不会对Bitmap进行一系列的屏幕适配,解析出来的将是原始大小的图
2、decodeResource在解析时会对Bitmap根据当前设备屏幕像素密度densityDpi的值进行缩放适配操作,使得解析出来的Bitmap与当前设备的分辨率匹配,达到一个最佳的显示效果,并且Bitmap的大小将比原始的大
1.1、关于Density、分辨率、-hdpi等res目录之间的关系
DensityDpi | 分辨率 | res | Density |
---|---|---|---|
160dpi | 320×533 | mdpi | 1 |
240dpi | 480×800 | hdpi | 1.5 |
320dpi | 720×1280 | xhdpi | 2 |
480dpi | 1080×1920 | xxhdpi | 3 |
560dpi | 1440×2560 | xxxhdpi | 3.5 |
px = dp * Density
1.2、DisplayMetrics::densityDpi与density的区别
getResources().getDisplayMetrics().densityDpi——表示屏幕的像素密度getResources().getDisplayMetrics().density——1dp等于多少个像素(px)
举个栗子:在屏幕密度为160的设备下,1dp=1px。在屏幕密度为320的设备下,1dp=2px。
所以这就为什么在安卓中布局建议使用dp为单位,因为可以根据当前设备的屏幕密度动态的调整进行适配
2、Bitmap的优化策略
2.1、BitmapFactory.Options的属性解析
BitmapFactory.Options中有以下属性:
2.2、优化策略
1、BitmapConfig的配置2、使用decodeFile、decodeResource、decodeStream进行解析Bitmap时,配置inDensity和inTargetDensity,两者应该相等,值可以等于屏幕像素密度*0.75f
3、使用inJustDecodeBounds预判断Bitmap的大小及使用inSampleSize进行压缩
4、对Density>240的设备进行Bitmap的适配(缩放Density)
5、2.3版本inNativeAlloc的使用
6、4.4以下版本inPurgeable、inInputShareable的使用
7、Bitmap的回收
针对上面方案,把Bitmap解码的代码封装成了一个工具类,如下:
一、decodeBitmap:对Bitmap不压缩,但是会根据屏幕的密度合适的进行缩放压缩
二、compressBimtap:对Bitmap进行超过最大宽高的压缩,同时也会根据屏幕的密度合适的进行缩放压缩。
3、Bitmap优化前后性能对比
针对上面方案,做一下性能对比,图片大小为3.26M,分辨率为2048*2048有两台设备:
3.1、density为320的设备
3.2、density为560的设备
可以看到,都是加载同一图片,在高屏幕像素密度的设备下所需要的内存需要很大、载入内存中的Bitmap的宽高也因设备的屏幕像素密度也改变,正如上面分析的一样,使用decodeResource会自动适配当前设备的分辨率达到一个最佳效果,而只有这个方法会自动适配其它方法将不会,依次思路,我们在封装的工具类中在每一个方法都加入了依屏幕像素密度来自动适配,而在实际中并不需要那么高清的图片,所以我们可以根据设备的density来进行缩放,比如:在400>=density>240的情况下x0.8,在density>400的情况下x0.7,这样Bitmap所占用的内存将减少非常多,可以对面上面两个图片中bitmap和decodeBitmap两个值的大小,decodeBitmap只是对density进行了一定的缩放,而占用内存却减少非常多,而且显示效果也和原先的并无区别。
之后对比我们进行了inSampleSize压缩的图片,进行压缩后的效果也看不出太大区别,而占用内存也减少了很多。
4、Bitmap的回收
4.1、Android 2.3.3(API 10)及以下的系统
在2.3以下的系统中,Bitmap的像素数据是存储在native中,Bitmap对象是存储在java堆中的,所以在回收Bitmap时,需要回收两个部分的空间:native和java堆。即先调用recycle()释放native中Bitmap的像素数据,再对Bitmap对象置null,保证GC对Bitmap对象的回收
4.2、Android 3.0(API 11)及以上的系统
在3.0以上的系统中,Bitmap的像素数据和对象本身都是存储在java堆中的,无需主动调用recycle(),只需将对象置null,由GC自动管理转载请注明:Android开发中文站 » Android性能优化之Bitmap的内存优化
相关文章推荐
- 我的 Android 开发实战经验总结
- ubuntu 15.10 搭建android-x86 qemu测试运行环境
- android baiduMap 以自己的定位为中心显示
- android无线调试
- android 判断手机号码格式
- Android中Toast如何在子线程中调用
- Android中使用Xutils库上传图片
- android中Handler源码的分析文章
- Android学习之使用Comparable或Comparator比较和排序元素
- android自定义view-打造圆形ImageView(二)
- Android 新闻客户端的学习
- Android开发笔记(五)
- Android开发笔记(四)
- Android开发笔记(三)
- 关于android.mk文件的作用、语法和自动添加源文件的学习
- android TextView 改变颜色
- [转载]android工程中引入另一个工程中的资源
- Exception_android_java.lang.NoClassDefFoundError
- 使用Android Studio的Live Templates——实现用少量的代码写出更多的代码
- Android-Tips(实用Android开发技巧)