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常见内存泄漏简单处理

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