Android内存泄漏(笔记)

来源:互联网 发布:客户资料整理软件 编辑:程序博客网 时间:2024/05/01 07:56

项目内存泄漏(笔记)

引言:

目前有个项目处于运营和维护阶段,用户量1000人左右,每天都有人反馈问题,而且从服务器查看崩溃日志,发现每天都有好多bug,总结了下,空指针的问题比较多,定位不准和定位失败也是个棘手的问题,这段时间尝试着解决这些问题,根本就是治标不治本,问题依然存在,影响了用户的使用,给他们的工作带来了不便。当前解决这些问题迫在眉睫。
由于刚接手这个项目,不知如何下手,只好根据反馈的问题切入。
好多bug在我手机上不重现,由于条件有限,不能每个机型都做测试,好多bug定位不到它的根本原因,这让我无从下手。
App经常闪退,当中肯定有内存泄漏,故打算把整个项目的内存泄漏问题检测一遍,挨个解决,不知道这个流程走完后闪退问题会不会所有改善,接下来这几天就着手解决这些问题,同时添加新的功能模块。

1.Android studio 检测内存:LeakCanary

在Build.gradle中添加
debugCompile ‘com.squareup.leakcanary:leakcanary-android:1.5’
releaseCompile ‘com.squareup.leakcanary:leakcanary-android-no-op:1.5’
在application中加上这一句:LeakCanary.install(this);//检测内存泄漏,然后运行程序,就会以通知栏的形式把内存泄漏的activity显示出来,逐个检测修改。

2.问题一

生命周期较长的类使用Activity的Context, 导致Activity被引用, 无法被及时回收. 除了需要Activity页面支持的控件类, 如Dialog等, 其他全部使用应用的Context替换Activity的Context, 即Context.getApplicationContext(). 还有就是单例不要持有页面的控件, 单例持有控件, 控件附属页面, 最终页面得不到释放, 单例可以使用回调修改页面, 内部仅仅保留处理数据部分.
截图
分析发现:Toast.makeText(this,….).show;这一句发生了泄漏 ,程序是进入一个页面,Toast了一下,然后finish了,可能是Toast持有了activity的引用,导致activity不能及时销毁
Toast有可能导致Activity泄漏。在创建Toast时,需要传入Context,如果这个Context是Activity,而Toast是异步弹出,有可能弹出时Activity已经结束。所以这里的正确使用方法,应该是传入ApplicationContext,避免Toast导致内存泄漏。

3.问题二

getSystemService 持有activity的实例导致了泄漏
这里写图片描述

这里写图片描述

工具类有个获取wifi信息的静态方法,调用这个方法时传的activity,应该是持有了activity的引用,activity销毁时发生了泄漏
谨慎使用getSystemService

4.那到底该用哪个Context?

摘录:
避免Android中Context引起的内存泄露:
http://droidyue.com/blog/2015/04/12/avoid-memory-leaks-on-context-in-android/
如果服务和UI相关,则用Activity
如果是类似ALARM_SERVICE,CONNECTIVITY_SERVICE建议有限选用Application Context
如果出现出现了内存泄漏,排除问题,可以考虑使用Application Context
所以,当我们再次使用getSystemService时要慎重考虑这样的问题。

5.慎用static

单例造成的内存泄漏
由于单例的静态特性使得其生命周期跟应用的生命周期一样长,所以如果使用不恰当的话,很容易造成内存泄漏
如果static 修饰的变量引用了context,此时传入 Application 的 Context

总结:

经过了一番修改,泄漏的地方少多了。之前撸代码没有考虑过内存泄漏的问题,以后会尽量避免。

0 0