Android 内存优化案例分析
案例下载地址:https://github.com/lzyzsd/MemoryBugs
下面利用内存检测工具对这个bug项目进行内存分析,将项目下载到手机上运行;此项目主界面上画了半个红色圆形,一行文字,还有两个按钮;第一按钮是启动。
问题1: AndroidStudio提供了Memory Monitor来实时显示应用运行时内存占用情况,下边蓝色部分是现在占用的内存,上面灰色的部分显示是已回收的内存。如果在图上看到尖峰,也就是快速分配内存又被回收,也就是发生了内存抖动,这里就是需要优化的地方。在模拟器或者真机中Debug项目,可实时监看Memory,CPU,NetWork等的资源占用情况。
从上图可以看出,运行程序时出现了内存突然升高,而且CPU也突然波动。所以可能是在程序中创建了多个对象,有及时释放时产生影响内存性能的现象。根据分析程序代码,可以找到出现问题的是下面这一段代码:
onDraw内创建对象解决方法:在方法外先建好对象,然后再在方法中引用。具体见工程代码。
问题2:通过leakcanary插件,可检查到内存泄露相关的代码,leakcanary检查运行截图如下:
第一:在activity中声明了静态变量造成内存泄漏
第二:使用Handler造成内存泄露
上面Handler的使用中当使用内部类(包括匿名类)来创建 Handler的时候,Handler对象会隐式地持有一个外部类对象(通常是一个Activity)的引用(不然就不可能通过Handler来操作 Activity中的View)。当activity关闭时,由于这时线程尚未执行完,而该线程持有Handler的引用,这个Handler又持有Activity的引用,就导致该Activity无法被回收(即内存泄露)。另外,执行了Handler的postDelayed()方法,该方法会将你的Handler装入一个Message,并把这条 Message推到MessageQueue中,那么在你设定的delay到达之前,会有一条MessageQueue -> Message -> Handler -> Activity的链,导致你的Activity被持有引用而无法被回收。
解决办法:
通过程序逻辑来进行保护
1.在关闭Activity的时候停掉你的后台线程。线程停掉了,就相当于切断了Handler和外部连接的线,Activity自然会在合适的时候被回收。
2.如果Handler是被delay的Message持有了引用,使用相应的Handler的removeCallbacks()方法,把消息对象从消息队列移除就行了。
将Handler声明为静态类
静态类不持有外部类的对象,所以Activity可以随意被回收。
下面是修改代码后的内存截图而且Leaks也不报内存泄漏:
网友评论