内存优化<上>
Android中Bitmap 内存分配的变化过程
- 3.0以前,Bitmap 对象放在Java堆,像素数据存放在 Native内存中,如果不手动调用 recycle ,那么Native内存中的像素数据完全依赖于 finalize 函数,而这个函数是不可靠的
- 3.0~7.0,Bitmap 对象和像素数据统一放到 Java 堆,这样就算不 recycle 操作,像素数据也会随着一起回收,不过,这导致大量内存占用,引起大量GC。一起放在内存也有可能即使系统有大量内存没利用,但是却会导致oom了(比如给分配的最大堆只到 300M,但是用得差不多了,此时系统却还空闲有3G内存,却要引起oom了)
- Android 8.0 中,NativeAllocationRegistry 可以满足Bitmap 对象存放在Java 堆,像素数据在 Native 中,还能实现一并回收对象和像素数据。(8.0还提供硬件位图(Hardware Bitmap),减少内存占用并提升绘制效率)
关于内存优化的两个误区
- 内存占用越小越好。不是这样的,更多的内存意味着更好的动画效果和更快的缓存命中,只需要做到系统内存充足时多用,系统内存紧张时少用(释放不是必须的内存)即可
- Native 的内存不用管。其实,当系统内存不足的时候,就会开始依次清理 后台、桌面、服务、前台,一步步来,直到内存足够,最后直到重启手机
内存观测方法
- 观察Log,查看GC 回收的原因
- 使用如下命令查看:
adb shell dumpsys meminfo <package_name|pid> [-d]
内存优化<下>
内存优化探讨
Bigmap 优化、内存泄露优化、设备分级几个层次入手
设备等级就是,在某些低性能的机器上,动画不要了,进程也不预先启动了。安装包大小也是有要求的,比如有很多app就有极速版这个概念,它们的apk很小,动画也不酷炫。apk大小跟内存的关系可以参考如下图:
Bitmap 可以用第三方框架来做,比如Fresco,实在要自己管理,可以向后台要求指定宽度,bitmap的inbitMap内存复用,inSample降低采样
内存泄露:使用LeakCanary自动化检测方案,只可以做到Activity和Fragment的泄漏检测,如何检测其他的内存泄露呢?如何监测疑似的内存泄漏呢?