Handler 内存泄漏和优化

在之前的项目中,Handler也使用,但往往是这么用的:

private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

        }
    };

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Message message = new Message();
        message.what = 1;
        mHandler.sendMessageDelayed(message,10*60*1000);
    }

今天听同事,说这样的会造成内存泄漏,建议用静态内部类,并弱引用,判断其Acitivity,自己也查询了百度相关资料,写下这篇,提醒自己。

造成内存泄漏的原因:非静态内部类会隐性地持有外部类的引用,二静态内部类则不会。在上面的代码中,Message在消息队列中延时了10分钟,然后才处理该消息。而这个消息引用了Handler对象,Handler对象又隐性地持有了Activity的对象,当发生GC是以为 message – handler – acitivity 的引用链导致Activity无法被回收,所以发生了内存泄露的问题。

当然简单的做法,可以在ondestroy()

 @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }

建议ondestory() 操作的同时,也改下handler

private NoLeakHandler mHandler;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mHandler = new NoLeakHandler(this);

        Message message = Message.obtain();
        message.what = 1;
        mHandler.sendMessageDelayed(message,10*60*1000);
    }

    static class NoLeakHandler extends Handler {
        private WeakReference<Activity> mActivity;
        public NoLeakHandler(Activity activity) {
            mActivity = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            final Activity activity = mActivity.get();
            if (activity != null) {
                switch (msg.what) {
                }
            }
        }
    }

通过弱引用Activity,判断Activity 的是否还存在,处理事情。
另外,新的代码将Message message = new Message(); 改成了 Message message = Message.obtain();
因为这种可以避免重复创建Message对象

Message 的使用有三种:
1.Message msg = new Message();
2.Message msg2 = Message.obtain();
3.Message msg1 = handler1.obtainMessage();

  1. 这种就是直接初始化一个Message对象,没有什么特别的

2.第二种,看源码

/**
     * Return a new Message instance from the global pool. Allows us to
     * avoid allocating new objects in many cases.
     */
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

从整个Messge池中返回一个新的Message实例,通过obtainMessage能避免重复Message创建对象。

  1. 第二种跟第三种其实是一样的,都可以避免重复创建Message对象,所以建议用第二种或者第三种任何一个创建Message对象。

所以,之后使用Handler 时,多加注意内存泄漏,和避免Message的重复创建。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值