Handler源码学习(四) - Handler源码学习

2018-11-28  本文已影响0人  Hoker_
东拉西扯讲了那么多,终于到Handler了。

一句话概括,Handler就是把特定任务发送到指定线程中执行,比如说UI刷新。如果没有这种需求,仅仅是需要线程的话,个人还是建议用线程池,因为代码更好写,而且线程池功能强大。

Handler的构造方法在前面文章里已经看过了,这里就不再继续说明。主要还是看看发送任务的方法,sendMessageAtTime(),其他的发送消息的方法最终都会调用到这个:

    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

方法非常简单,就是对Handler绑定的消息队列发送消息,需要注意的是:

msg.target = this;

这里会把Handler对象的引用也放到消息队列里,方便消息队列来识别是哪个Handler的消息被消费。

结合前面的几个分析,Handler源码也没啥特别好讲的了,在说下平时使用Handler经常出的内存泄漏问题吧。

要知道,android内存回收,是采用GCRoot判断引用是否可达来决策的,换句话说,以GCRoot为起点,它可以引用到的对象,在GC时都不会被回收,其他的则会被回收,那么GCRoot有哪些呢:

  • 运行中的线程
  • 静态对象
  • 来自native code中的引用

一般的,我们大多数都是在Activity里这么写上handler:

    private final Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //执行任务
        }
    };

但是,内部类(包括匿名类)来会隐式地持有一个外部类对象的引用(在这里就是Activity,不然是无法在里Handler来操作Activity中的View的)而且,我们使用Handler绑定的都是主线程,而主线程的生命周期显然是整个APP运行时期。假如使用Handler的postDelayed()方法,那么在设定的delay到达之前,会有一条Looper->MessageQueue -> Message -> Handler -> Activity的链,导致Activity被持有引用而无法被回收。

解决方法也很简单,用静态类+弱引用:

    public static class MyHandler extends Handler{

        WeakReference<MainActivity> mWeakReference;
        
        public MyHandler(MainActivity activity){
            mWeakReference=new WeakReference<MainActivity>(activity);
        }
        
        @Override
        public void handleMessage(Message msg){
            final MainActivity activity=mWeakReference.get();
            if(activity!=null){
                super.handleMessage(msg);
                //执行任务
            }
        }
    }

由于是弱应用,这样在Activity不再使用时,可以被GC掉。

总结:Handler是就是安卓的消息机制,熟悉其原理对平时工作有很大的帮助。
上一篇下一篇

猜你喜欢

热点阅读