- 内存泄漏:当你不再需要某个实例后,但是这个对象却仍然被引用,防止被垃圾回收。这个情况就叫做内存泄露(Memory Leak)。
常见泄漏场景:
1.Handler 导致的内存泄漏
|
|
原理浅析
当 Android 应用程序启动时,framework 会为该应用程序的主线程创建一个 Looper 对象,负责轮询从Message Queue取数据。
当在主线程中实例化一个 Handler 对象后,会自动与主线程 Looper 的消息队列关联起来。当 Activity 已经结束/销毁,而handmerssage有未处理完的消息时(既message持有Message Queue持有 Handler持有当前 Activity 引用)此时就极有可能导致内存泄漏。
|
|
- 方案1:静态内部类加 WeakRefrence。
- 方案2:当退出activity时,要注意所在Handler消息队列中的Message是否全部处理完成,可以考虑
removeCallbacksAndMessages(null)
手动关闭
2.静态变量导致内存泄漏
|
|
可能导致内存泄漏,原因是:静态变量持有当前 Activity。导致当前 Activity 结束时候,静态变量仍然持有它的引用。可以参见[Android静态变量的生命周期]。建议少引用,或者及时需要手动置空。
3.单利模式导致内存泄漏,如果用到Context ,尽量用ApplicationContext
|
|
4.非静态内部类持有外部类的实例
|
|
因为非静态内部类持有外部类对象的引用。正确的做法为: 将该内部类设为静态内部类或将该内部类抽取出来封装成一个单例,如果需要使用Context,请使用ApplicationContext。
5.线程造成的内存泄漏
Runnable 是一个匿名内部类( AsyncTask 存在匿名内部类的情况),对当前 Activity 都有一个隐式引用。实例代码如下:
|
|
当你执行耗时任务,在onDestroy()
的时候考虑调用Thread.close()
,如果对线程的控制不够强的话,可以使用RxJava自动建立线程池进行控制,并在生命周期结束时取消订阅;
在使用AsyncTask时,在Activity销毁时候也应该取消相应的任务AsyncTask.cancel()方法,避免任务在后台执行浪费资源,进而避免内存泄漏的发生。
6.属性动画导致内存泄漏
属性动画中有一类无线循环的动画,要及时取消,否则最终导致 Activity 无法被释放。动画的特征代码如下:
|
|
解决办法自然很简单,在 OnDestory() 中去取消动画即可.
7.资源未关闭造成的内存泄漏
对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。
其他 :
- 广播泄露:手动注册广播时,记住退出的时候要
unregisterReceiver()
- 第三方SDK/开源框架泄露:ShareSDK, JPush等第三方SDK需要按照文档控制生命周期
- 各种callBack/Listener的泄露,要及时设置为Null,特别是static的callback
- 某些Service也要及时关闭,比如图片上传,当上传成功后,要
stopself(),建议用intentservice。
- Webview需要手动调用
WebView.onPause()
以及WebView.destory()
多用泄露检测LeakCanary
开始使用
1.在
build.gradle
中加入引用,不同的编译使用不同的引用:dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3' }
2.在
Application
中:public class ExampleApplication extends Application { @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); } }
详见LeakCanary 中文使用说明
https://www.liaohuqiu.net/cn/posts/leak-canary-read-me/
这样,就万事俱备了! 在 debug build 中,如果检测到某个 activity 有内存泄露,LeakCanary 就是自动地显示一个通知。
参考:
http://www.jianshu.com/p/c59c199ca9fa
http://allenwu.itscoder.com/2016/10/21/allenwu_20161023_oom_in_android_and_solution/