详解详解Android性能优化之内存泄漏性能优化之内存泄漏
综述综述
内存泄漏(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的工作过程)
情景五:第三方库使用不当情景五:第三方库使用不当
对于EventBus,RxJava等一些第三开源框架的使用,若是在Activity销毁之前没有进行解除订阅将会导致内存泄漏。
使用使用MAT检测内存泄漏检测内存泄漏
对于常见的内存泄露进行介绍完以后,在这里再看一下使用MAT(Memory Analysis Tool)来检测内存泄露。MAT的下载地址为:http://www.eclipse.org/mat/downloads.php。
下面来看一段会导致内存泄露的错误代码。
public class LeakActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);