声明:本文内容来源于 的汇总:Android性能优化之利用LeakCanary检测内存泄漏及解决办法 - 总李写代码 - 博客园 和 Android性能优化_wall0920的技术博客_51CTO博客,向作者表示感谢
内存泄露和内存溢出
1.有些对象只有有限的生命周期。当它们的任务完成之后,它们将被垃圾回收。如果在对象的生命周期本该结束的时候,这个对象还被一系列的引用,这就会导致内存泄漏。随着泄漏的累积,app将消耗完内存。
2.内存溢出是App为1个对象申请内存空间,内存空间不足的情况.out of memory.
内存泄露造成的影响
它是造成应用程序OOM的主要原因之一。由于android系统为每个应用程序分配的内存有限,当一个应用中产生的内存泄漏比较多时,就难免会导致应用所需要的内存超过这个系统分配的内存限额,这就造成了内存溢出而导致应用Crash。
常见内存泄露案例
1)错误使用单例造成的内存泄漏
Q:而在开发中单例经常需要持有Context对象,如果持有的Context对象生命周期与单例生命周期更短时,或导致Context无法被释放回收,则有可能造成内存泄漏
A:要保证Context和AppLication(getApplicationContext())的生命周期一样
2)Handler造成的内存泄漏
Q:通过内部类的方式创建mHandler对象,此时mHandler会隐式地持有一个外部类对象引用这里就是MainActivity,当执行postDelayed方法时,该方法会将你的Handler装入一个Message,并把这条Message推到MessageQueue中,MessageQueue是在一个Looper线程中不断轮询处理消息,那么当这个Activity退出时消息队列中还有未处理的消息或者正在处理消息,而消息队列中的Message持有mHandler实例的引用,mHandler又持有Activity的引用,所以导致该Activity的内存资源无法及时回收,引发内存泄漏
A:要想避免Handler引起内存泄漏问题,需要我们在Activity关闭退出的时候的移除消息队列中所有消息和所有的Runnable。上述代码只需在onDestroy()函数中调用mHandler.removeCallbacksAndMessages(null);就行了
3)线程造成的内存泄漏
Q:AsyncTask在处理耗时的操作时,可能还没处理结束Activity就执行了退出操作,但是此时AsyncTask依然持有对MainActivity的引用就会导致MainActivity无法释放回收引发内存泄漏。
A:在使用AsyncTask时,在Activity销毁时候也应该取消相应的任务AsyncTask.cancel()方法,避免任务在后台执行浪费资源,进而避免内存泄漏的发生。
4)非静态内部类创建静态实例造成的内存泄漏
5)由WebView引起的内存泄漏
6)资源未关闭造成的内存泄漏
性能优化
1)过度绘制
Q:Overdraw过度绘制是指屏幕上的某个像素在同一帧的时间内被绘制了多次.过度绘制会大量浪费CPU及GPU资源/占用CPU和GPU的处理时间
- 过度绘制的原因
- UI布局存在大量重叠
- 非必须的背景重叠.
- 如Activity有背景,Layout又有背景,子View又有背景.仅仅移除非必要背景就可以显著提升性能.
- 子View在onDraw中存在重叠部分绘制的情况,比如Bitmap重叠绘制
A:解决办法
- 移除XML布局文件中非必要的Background
- 保持布局扁平化,尽量避免布局嵌套
- 在任何时候都避免调用requestLayout(),调用requestLayout会导致该layout的所有父节点都发生重新layout的操作
- 在自定义View的onDraw中避免过度绘制
- 尽量减少每次重绘的元素可以极大提升性能,可以把复杂的View拆分会更小的View进行组合,在需要刷新界面时候仅对指定View进行重绘.
- 可以使用include标签引入其他布局文件中,尤其当出现比较通用的view的时候,比如自定义的标题栏或底部菜单栏
2)如何避免OOM
- 减小对象的内存占用
- 内存对象复用防止重建
- 避免使用枚举,用注解替代
- 减小创建的Bitmap的内存,使用合适的缩放比例及解码格式 例如:inSampleSize:缩放比例;decode format:解码格式
- 对象池技术:减少频繁创建和销毁对象带来的成本,实现对象的缓存和复用
- 尽量使用Android系统内置资源,可降低APK大小,在一定程度降低内存开销
- 在for循环中,用StringBuilder代替String实现字符串拼接
- 资源对象要及时关闭
- Context:尽量使用Application Context而不是Activity Context,避免不经意的内存泄漏