Android内存优化
一、内存管理方式
1、
2、
3、
1)dumpsys meminfo +包名查看堆栈信息
①
②
MEMINFO in pid 5073 [com.android.mooc.hexter.memopti]
进程5073
包名:com.android.mooc.hexter.memopti
pss:物理内存的使用情况
Heap Size:堆的尺寸
Heap Alloc:堆分配了多少
Heap Free:堆富余了多少
Native Heap: JNI开发中的堆
Dalvik Heap:虚拟机的堆
Stack:堆栈的大小
Ashmem:共享内存的大小
.so mmap: .so的内存使用
.apk mmap: apk的内存使用
2)不用的内存、不用的垃圾由GC负责处理。GC只有在堆Heap的剩余空间不够时才发出垃圾回收,但是垃圾不会马上放到free heap空间里面,只有当下次回收时发现空间不够了,GC才会在自己的堆里面把垃圾全部都清理掉,释放给free的空间,如果此时剩余空间够了,则直接在剩余空间中进行分配。
4、
如果一个app把内存占光,则企业的app则无法运行
5、
①
②LRU算法:最近使用的排在最前面,最少可能的被清理掉
③内存变动时会毁掉onTrimMemory方法,会把系统内存的level打印出来,判断level值释放手机内存
二、APP内存优化方法
1、
2、
1)字符串通过+的方式进行字符串拼接,会产生中间字符串内存块,这些都是没有用的
2)字符串拼接和Stringbuilder方式拼接字符串耗时比较
①
给二维矩阵赋值
字符串拼接的代码
StringBuilder拼接代码
②
点击字符串拼接的按钮:刚开始拼接运行速度挺快的,都是毫秒级别,后来越来越慢,都是秒的级别
耗时大概8s左右
③点击StringBuilder拼接的按钮:几乎是瞬间完成,只用了3毫秒,比上一种方式快了不仅仅一点点
3、ArrayMap、SparseArray替换HashMap,调用方法是一样的,但是使用效率比HashMap高。一方面,内存使用更少,第二方法,如果数据比较多,这两个效率比较高
4、内存抖动是变量申请不当引起的。比如说突然申请了很多变量或多内存空间,但是很快不用了,但是又申请了很多内存。就是很快申请很多内存又很快不用,从monitor中可以看到锯齿一样的内存很快提高又很快下来,就是内存抖动。内存抖动时间过长就会影响app运行的流畅性。
代码:
优化:
将strMatrix变量放在外面,重复使用
5、
6、
7、内存泄漏
引起的原因:
内部类默认是引用activity的引用的,当tread中执行了耗时操作,activity退出后,线程仍然在运行,由于持有了外部类的引用,导致activity无法被gc回收,可以使用的堆越来越小。如果线程中没有执行耗时操作,是不会引起问题的,执行完就销毁,不会持有外部类的引用,gc就可以回收activity。解决办法就是将其放在service中
8、
三、OOM问题优化
1、
1)
变量的声明周期是和变量申请的声明周期一样的,在变量声明周期内,变量是不会被gc回收的。
软引用与强引用的声明周期是一样的,但是运行过程中可以被gc回收
2、
得到内存变化的通知
level的值
3、
4、
代码:
第一个按钮:获取并打印图片
第二个按钮进行优化后:根据屏幕的宽高只获取图片的宽高,进行压缩后进行显示
第三个按钮,直接修改RGB
第四个按钮:部分加载图片
5、软引用方式管理图片
单例模式
放图片的时候先清理缓存,因为有的软引用使用的图片已经被回收了,然后再放入数据
获取图片,如果存在,返回图片
清理缓存。系统回收软引用,遍历队列,如果不为空,从map中移除
清空所有数据
通过软引用管理多张图片,不好的地方就是回收图片是随机的,可能回收的图片下次还需要使用
6、内存缓存,使用了lru算法
linkhashmap专门用来管理lru算法,因为线程不安全,所以外面套了一个synchronizemap
获取相应的图片
存储图片,如果原来存在图片,需要更新。
减去原来的尺寸是因为要放入新的图片,放入新的图片,原来的图片就放弃掉了。放入新的图片时加上新图片的大小
判断是否大于最大限制,如果大于获取迭代器。从最近最少用的图片开始进行迭代,获取到相应的图片。减去其大小,实际上就是放弃掉了,然后remove掉。remove掉后说明最近很少用的图片就被释放掉了,释放掉后gc就会回收。如果释放后还大于最大限制,则不停地释放,直到满足条件为止。
注:
1、参考资料:https://www.imooc.com/video/13670
2、ps命令查看进程id和堆大小
5、健康内存的击中方法
①
②通过代码打印内存信息
③使用Android Monitor监控
内存变换情况
③
Tools-->Android-->Android Device Monitor
点击获取GC数据