(点击
上方公众号
,可快速关注)
来源:
无嘴小呆子
链接:
blog.csdn.net/ljd2038/article/details/53560829
综述
内存泄漏(memory leak)是指由于疏忽或错误造成程序未能释放已经不再使用的内存。那么在Android中,当一个对象持有Activity的引用,如果该对象不能被系统回收,那么当这个Activity不再使用时,这个Activity也不会被系统回收,那这么以来便出现了内存泄漏的情况。在应用中内出现一次两次的内存泄漏获取不会出现什么影响,但是在应用长时间使用以后,若是存在大量的Activity无法被GC回收的话,最终会导致OOM的出现。那么我们在这就来分析一下导致内存泄漏的常见因素并且如何去检测内存泄漏。
导致内存泄漏的常见因素
情景一:静态Activity和View
静态变量Activity和View会导致内存泄漏,在下面这段代码中对Activity的Context和TextView设置为静态对象,从而产生内存泄漏。
import
android
.
content
.
Context
;
import
android
.
support
.
v7
.
app
.
AppCompatActivity
;
import
android
.
os
.
Bundle
;
import
android
.
widget
.
TextView
;
public
class
MainActivity
extends
AppCompatActivity
{
private
static
Context
context
;
private
static
TextView
textView
;
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
setContentView
(
R
.
layout
.
activity_main
);
context
=
this
;
textView
=
new
TextView
(
this
);
}
}
情景二:Thread,匿名类,内部类
在下面这段代码中存在一个非静态的匿名类对象Thread,会隐式持有一个外部类的引用LeakActivity,从而导致内存泄漏。同理,若是这个Thread作为LeakActivity的内部类而不是匿名内部类,他同样会持有外部类的引用而导致内存泄漏。在这里只需要将为Thread匿名类定义成静态的内部类即可(静态的内部类不会持有外部类的一个隐式引用)。
public
class
LeakActivity
extends
AppCompatActivity
{
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
setContentView
(
R
.
layout
.
activity_leak
);
leakFun
();
}
private
void
leakFun
(){
new
Thread
(
new
Runnable
()
{
@Override
public
void
run
()
{
try
{
Thread
.
sleep
(
Integer
.
MAX_VALUE
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
}
});
}
}
情景三:动画
在属性动画中有一类无限循环动画,如果在Activity中播放这类动画并且在onDestroy中去停止动画,那么这个动画将会一直播放下去,这时候Activity会被View所持有,从而导致Activity无法被释放。解决此类问题则是需要早Activity中onDestroy去去调用objectAnimator.cancel()来停止动画。
public
class
LeakActivity
extends
AppCompatActivity
{
private
TextView
textView
;
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
setContentView
(
R
.
layout
.
activity_leak
);
textView
=
(
TextView
)
findViewById
(
R
.
id
.
text_view
);
ObjectAnimator
objectAnimator
=
ObjectAnimator
.
ofFloat
(
textView
,
"rotation"
,
0
,
360
);
objectAnimator
.
setRepeatCount
(
ValueAnimator
.
INFINITE
);
objectAnimator
.
start
();
}
}
情景四:Handler
对于Handler的内存泄漏在(Android的消息机制——Handler的工作过程)[http://blog.csdn.net/ljd2038/article/details/50889754]这篇文章中已经详细介绍,就不在赘述。
情景五:第三方库使用不当
对于EventBus,RxJava等一些第三开源框架的使用,若是在Activity销毁之前没有进行解除订阅将会导致内存泄漏。
使用MAT检测内存泄漏
对于常见的内存泄露进行介绍完以后,在这里再看一下使用MAT(Memory Analysis Tool)来检测内存泄露。MAT的下载地址为:http://www.eclipse.org/mat/downloads.php。
下面来看一段会导致内存泄露的错误代码。
public
class
LeakActivity