Android常见内存泄漏简单处理

作者: 深情不及酒伴 | 来源:发表于2017-09-07 13:31 被阅读0次

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

什么是内存泄漏?

内存泄漏(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> activity= null;

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

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

内存泄漏检查工具

leakcanary

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

相关文章

  • Android常见内存泄漏简单处理

    本篇文章主要说一下项目结束时简单的内存泄漏检查与处理。 什么是内存泄漏? 内存泄漏(memory leak):是指...

  • 带你学开源项目:LeakCanary-如何检测 Activity

    OOM 是 Android 开发中常见的问题,而内存泄漏往往是罪魁祸首。为了简单方便的检测内存泄漏,Square ...

  • Android内存泄漏检测和定位

    建议阅读Android常见内存泄漏这篇文章,本文的例子来源于文章中的内存泄漏典型例子 内存泄漏检测工具 Profi...

  • Android内存泄漏原因及解决的总结

    分三步说明Android内存泄漏的原因及解决,“内存泄漏与内存溢出的区别”,“引用方式”,“常见引发原因与解决方案...

  • Android-推荐一个检测内存泄漏的库(LeakCanary)

    在Android开发当中,内存泄漏是会影响用户体验的。LeakCanary开源库是一个常见的定位内存泄漏的开源库,...

  • 科普 - 收藏集 - 掘金

    5 个 Android 开发中比较常见的内存泄漏问题及解决办法 - Android - 掘金在Android开发中...

  • Android 优化

    Android 内存优化内存溢出 , 内存泄漏 , 内存泄漏过多就导致内存溢出 Android 系统垃圾回收机制内...

  • Android 常见内存泄漏

    构造单例的时候尽量别用Activity的引用; 静态引用时注意应用对象的置空或者少用静态引用; 使用静态内部类+软...

  • Android 常见内存泄漏

    一、单例造成的内存泄漏Android的单例模式非常受开发者的喜爱,不过使用的不恰当的话也会造成内存泄漏。因为单例的...

  • Android - 常见内存泄漏

    单例 单例静态对象持有activity引用,且因静态对象生命周期比activity还长,当act被销毁时,单例中的...

网友评论

    本文标题:Android常见内存泄漏简单处理

    本文链接:https://www.haomeiwen.com/subject/rogbjxtx.html