Android常见内存泄漏简单处理

本篇文章主要说一下项目结束时简单的内存泄漏检查与处理。

什么是内存泄漏?

内存泄漏(memory leak):是指应用在申请资源(内存)后,资源(内存)没有得到及时的释放。
区别:
内存溢出(out of memory): 是指应用在申请内存是,没有足够的内存供其使用,出现了out of memory。

内存泄漏的危害:

大量的内存泄漏最终会导致内存溢出(OOM)。

常见的导致内存泄漏的现象:

一、Handler引起的内存泄漏。

Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        mTextView.setText("星期四");
    }
}

很常见的一段代码,handler通知UI线程更新UI。
当Handler使用内部类(包括匿名类)来创建的时候,handler会隐式的持有一个外部类对象(通常是Activity)的引用,当耗时操作结束,页面关闭
,因为handler持有activity的引用,导致activity不能被正常GC正常回收,从而导致内存泄漏

解决办法

Activity销毁的时候调用handler的removeCallbacks()方法

二、单利模式引起的内存泄漏。

 public static SingleInstance getInstance(Context context) {  
        if (instance == null) {  
            instance = new SingleInstance(context);  
        }  
        return instance;  
    }  

单利模式只是这类原因的一种表现。不单是单利,凡是

长生命周期对象持有短生命周期对象,导致短生命周期对象不能回收。

的现象都会导致内存泄漏现象,

解决办法

使用Application中的Context。

三、非静态内部类创建静态实例引起的内存泄漏

public class TestActivity extends Activity {
    private static Hello sHello = null;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (sHello == null)
            sHello=new Hello();
    }
    class Hello{
    }
}

非静态的内部类会自动持有外部类的引用。
而使用非静态的内部类创建了一个静态实例(sHello) ,sHello 的生命周期和应用的生命周期一样长,sHello 会一直持有activity的引用,使activity无法被回收,从而导致内存泄漏。

解决办法

将内部类(Hello)改为静态内部类,因为静态内部类不在持有外部类的引用

static class Hello{
}

四、非静态匿名内部类引起的内存泄漏

非静态匿名内部类,会自动持有外部类的引用

 mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
            }
        }, 1000 * 60);

上面写了一个延迟的消息,被延迟的消息会在消息队列中存在60秒,这个消息中包含了handler的引用,Handler是一个匿名内部类的实例,持有了外部类(Activity)的实例,此时关闭activity,activity无法被回收,导致内存泄漏。而new Runnable这里也是匿名内部类实现的,同样也会持有Activity的引用,也会阻止Activity被回收。

解决办法:

把匿名内部类设置为静态的,这样就不会自动持有外部类的引用,也就不会引起内存泄漏了。

 private static final Runnable sRunnable = new Runnable() {
        @Override
        public void run(){
        }
    };

Handler会持有Activity的引用,使用弱引用保存Activity。

五、注册,绑定后没有解除注册,绑定。

   @Override
    public void onDestroyView() {
        super.onDestroyView();
        unbinder.unbind();
    }

还有广播等需要注册的都需要解除注册。

六、资源对象没有关闭、释放、复用起的内存泄漏

资源性对象比如(Cursor,File文件等)没有关闭,
图片处理时Bitmap.recycle(),
ListView复用

Activity引起的内存泄漏。

使用若引用来保存Activity

 private WeakReference activity= null;

 public void setActivity(Activity activity) {
        this.activity = new WeakReference(activity);
 }

 public Activity getActivity() {
        return activity.get();
 }

内存泄漏检查工具

leakcanary

常见OOM及解决方法:https://www.cnblogs.com/scetopcsa/p/4005398.html

你可能感兴趣的:(Android常见内存泄漏简单处理)