第一章 内存优化
内存优化,这是android开发必经之路,那么怎样去优化呢?
首页先看看内存方面面临问题
- (1)有限的堆内存,原始只有16M
- (2)内存消耗和设备、操作系统、屏幕尺寸等因素有关系
- (3)程序不能直接控制
- (4)支持后台多任务
- (5)运行在虚拟机上
内存泄漏和内存溢出区别
- 内存溢出(out of memony):在想程序申请内存时,没有足够的内存使用,导致内存溢出,比如:一-个Integer变量,给他一个Long类型的数据,那肯定溢出了。
- 内存泄漏(memony leak):程序申请内存后,没有释放,一直占有内存,一次内存泄漏可以忽略,但是内存时有限的,迟早会占满。
其中内存泄漏可以分为4类
- 常发性内存泄漏:经常申请内存还不释放内存,能明确查到的这类型泄漏
- 偶发性内存泄漏:偶然(在特定环境下)申请内存,造成内存泄漏
- 一次性内存泄漏:只有一个申请内存,造成内存泄漏
- 隐世行内存泄漏:程序运行过程中,不停分配内存,直到程序运行完成后,再释放。这类型泄漏危害比较大
内存泄漏造成的影响
- 程序变慢了,卡顿了,相应速度变慢了(内存占用过高,JVM会频繁gc)
- 莫名消失,在后台占用时间过长,会被杀死
- 直接奔了
第一步 查看内存使用情况
观察和计算系统内存使用情况,可以使用Android提供给我们的两个工具procstats,meminfo。他们一个侧重于后台的内存使用,另一个是运行时的内存使用
- Procstats:可以去监视你app在一段时间的行为,包括在后台运行了多久,并在此段时间使用了多少内存。从而帮助你快速的找到应用中不效率和不规范的地方去避免影响其performs,尤其是在低内存的设备上运行时。
- 通过adb shell命令去使用procstats(adb shell dumpsys procstats –hours 3)
- meminfo:它是根据PSS标准 (Proportional Set Size——实际物理内存)计算每个进程的内存使用并且按照重要程度排序。
第二步 减少内存占用
(1)使用更加轻量的数据解决
- 我们可以考虑使用ArrayMap/SparseArray而不是HashMap等传统数据结构
- SparseArray可以避免AutoBox,查找方法为二分查找,效率比HashMap低一些
(2)避免在Android里面使用Enum
官方文档是这样说的,枚举相对于静态常量来说,需要两倍甚至更多的内存
(3)Bitmap
Bitmap是内存消耗大户,绝大多数的OOM崩溃都是在操作Bitmap时产生的,下面来看看几个处理图片的方法:
图片显示
根据需求显示图片,例如,显示缩略图图时用小图,当用户点击后,显示完整的大图。
图片大小
显示图片的时候,要对图片大小进行处理,不要直接用ImageView,来直接显示,可以使用BitmapFactory.Options设置缩放比例。
图片像素
Android中图片有四种属性,分别是:
- ALPHA_8:每个像素占用1byte内存
- ARGB_4444:每个像素占用2byte内存
- ARGB_8888:每个像素占用4byte内存 (默认)
- RGB_565:每个像素占用2byte内存
Android默认的颜色模式为ARGB_8888,这个颜色模式色彩最细腻,显示质量最高。但同样的,占用的内存也最大。 所以在对图片效果不是特别高的情况下使用RGB_565(565没有透明度属性)
publicstaticBitmapreadBitMap(Contextcontext, intresId) {
BitmapFactory.Optionsopt = newBitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable = true;
opt.inInputShareable = true;
//获取资源图片
InputStreamis = context.getResources().openRawResource(resId);
returnBitmapFactory.decodeStream(is, null, opt);
}
图片回收
使用Bitmap过后,就需要及时的调用Bitmap.recycle()方法来释放Bitmap占用的内存空间,而不要等Android系统来进行释放。
// 先判断是否已经回收
if(bitmap != null && !bitmap.isRecycled()){
// 回收并且置为null
bitmap.recycle();
bitmap = null;
}
System.gc();
捕获异常
在压缩图片的过程中,如果图片是大图,则非常容易造成oom,所以这里要捕获异常,对压缩失败的图片进行处理
(4)对象引用类型
引用类型:强引用,软引用,弱引用,虚引用,(这里就不做解释)
利用四种引用能够解决一些问题,例如如果想避免OutOfMemory异常的发生,则可以使用软引用。
如果对于应用的性能更在意,想尽快回收一些占用内存比较大的对象,则可以使用弱引用。
还有就是可以根据对象是否经常使用来判断。
如果该对象可能会经常使用的,就尽量用软引用。如果该对象不被使用的可能性更大些,就可以用弱引用。
另外,和弱引用功能类似的是WeakHashMap。WeakHashMap对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的回收,回收以后,其条目从映射中有效地移除。WeakHashMap使用ReferenceQueue实现的这种机制。
(5)了解使用的类
- 在用处理字符串时候,可以使用String.indexOf(),String.lastindexOf()等实现方法;
- 在使用ArrayList时候,尽量初始化就写好大小,这样减少数组的重复移动;
- 还有在使用for循环中,在尽量直接复制count,不要使用this.getCount等。
- 尽量少的使用浮点数
- 避免频繁调用的类中使用get和set方法,可以直接访问变量。
- 尽量不要创建没必要的对象。
- 对应的常量使用static final