android内存泄漏

开发app中对内存的使用,一定是大家最关心的问题之一,因为内存的使用直接影响到app的性能。

内存使用中内存泄漏是开发Android应用中常见的,Android中可以使用LeakCanary来检测内存泄漏。

那么什么是内存泄漏?

内存泄漏简单解释就是:完全无用的对象,无法被被GC回收的现象就是内存泄漏。

内存泄漏会造成什么问题呢?

每个app可分配的内存是有限的,内存泄漏就会占有一块内存,过多的内存泄漏就会导致内存超出app可用的内存,导致内存溢出,app就奔溃了(引发Out Of Memory)。

接下来我们带着三个问题来分析下内存泄漏:

1.经常会出现内存泄漏的地方有哪些?

2.为什么会出现?

3.如何避免内存泄漏?

一.单例模式造成的内存泄漏:
    public class Signleton {
        private static Signleton mSignleton;
        private Context mContext;
        private Signleton(Context context){
            this.mContext = context;
        }
        public static Signleton getInstance(Context context){
            if (mSignleton == null){
                mSignleton = new Signleton(context);
            }
     
            return mSignleton;
        }
    }

这里为什么会出现内存泄漏呢?

因为单例模式的生命周期和应用程序是一样长的,所以当我们在一个activity中调用这个单例,传入activity作为context,单例就持有了这个activity的引用,而当我们退出这个activity时,由于单例的生命周期是同应用程序一样长,所以这个单例还持有activity的引用,这个activity对象就不会被回收,这时就造成了内存泄漏。

如何解决:

    private Signleton(Context context){
        this.context = context.getApplicationContext();
    }

这里我们改成不管传入的context是activity还是其他的都转换为整个应用程序的context,这样生命周期就和单例一样长,就避免了内存泄漏。

二.非静态内部类造成的内存泄漏:
    private final String TAG = "DemoActivity";
    private static Interior mInterior;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        if (mInterior == null){
            mInterior = new Interior();
        }
    }
    class Interior{}

这里为什么会出现内存泄漏呢?

这个activity中有一个非静态内部类,因为非静态内部类中隐式持有外部类的引用,所以内部类Interior中就持有activity的引用,

例子中静态变量mInterior的生命周期是和应用程序一样长的,而该静态变量中又持有activity的引用,所以到activity销毁时,回收activity的时候无法被回收,就出现了内存泄漏。

如何解决:

    static class Interior{
     
    }

把该非静态内部类改成静态内部类就可以了(因为静态内部类不会持有外部的引用)。

三.Handler造成的内存泄漏:
    private void toHandler(){
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                tvTitle.setText("hello");
            }
        },1000);
    }

这里为什么会出现内存泄漏呢?

这段代码中有两个方面会造成内存泄漏:

1.Runnable是匿名内部类,持有Activity的 TextView会造成内存泄漏。

2.TextView持有Activity 的强引用,这样也会造成内存泄漏。

因为handler的消息机制,当Activity销毁,handler中还有为处理的Message时就会持有activity的引用从而导致无法被回收,出现内存泄漏。

如何解决:

方法1:改成静态内部类+弱引用

    private static class DemoRunnable implements Runnable{
        private WeakReference<TextView> wTextView;
        protected DemoRunnable(TextView textView){
            wTextView = new WeakReference<TextView>(textView);
        }
        @Override
        public void run() {
            wTextView.get().setText("hello");
        }
     
    }

方法2:在Activity的onDestory中移除mHandler的所有Message

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }
四.线程造成的内存泄漏:

线程的内存泄漏同Handler一样也是匿名内部类Runnable造成的,解决方式同handler方法1一样。

五.资源未关闭造成的内存泄漏:

主要使用的资源:

1.BraodcastReceiver

2.ContentObserver

3.File

4.Cursor

5.Stream

6.Bitmap

这些资源的使用都需要在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,从而造成内存泄漏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值