Handler机制到底是个什么东西?(一句话说清楚)

“说一下handler机制”,这句话面试的时候被问过无数次。但是到底要怎么说,网上却没有一个标准答案,很多人洋洋洒洒一大篇加各种图,实在让人望而生畏,你是让我面试的时候背这么一大篇吗?

其实真的没有那么复杂,干货上前,标准答案:

   Handler机制主要由Handler,Looper,MeesageQueue组成。
   Looper在程序启动时即创建并不断的在循环,直到Handler有消息发送到MessageQueue时,
   Looper取出消息且回调给Handler来处理。

怎么样,洋洋洒洒一大篇看不懂,这么几句话,是不是简单多了?

什么,你说不够深入?

好吧,那我们来深入一下,《How to read a book》讲,一定要提出问题,那我们就来深入的提出几个问题:

1.Looper是个什么玩意,它是怎么创建的?它是什么时候开始循环的?

2.Handler是怎么把发送消息让Looper知道的?

3.Looper又是怎样取出消息且回调给Handler来处理的?

在这里,我们必须阅读一下源码了,我们来看这三个主要组成的其一Looper类,打开代码,是不是很长一大片不知道怎么入手?哎呀好困难怎么办。答案是,一点也不困难,因为我们阅读源码,并不是一行一行读,而是只要看核心方法就够了,什么是核心方法呢?Looper有俩个,prepare(),这个单词的意思是准备;还有一个loop(),这个单词的意思是循环。

我们来看perpare()

    static final ThreadLocal sThreadLocal = new ThreadLocal();
    final MessageQueue mQueue;
    final Thread mThread;

    public static void prepare() {
        prepare(true);
    }
    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }
    
    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

是的没有错,就这些了,我们可以看到它做了三件事情:
第一、“sThreadLocal.set(new Looper(quitAllowed));” 把new出来的Looper给塞到ThreadLocal里面,我们不难理解ThreadLocal就是一个类似HashMap的东东;
第二、“ mQueue = new MessageQueue(quitAllowed);” new了一个MessageQueue;
第三、“mThread = Thread.currentThread();” 获取当前线程的引用。

接下来是loop()

   public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            try {
                msg.target.dispatchMessage(msg);
            } finally {
           
            }
            msg.recycleUnchecked();
        }
    }

把不重要的代码删掉,是不是一目了然了,已经不用多解释了吧?

我们再来看一个类,ActivityTread的main[]方法,这个地方是程序启动时就会调用的

    public static void main(String[] args) {
        Looper.prepareMainLooper();
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

    class Looper{
      public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
}

一目了然,也就是说,程序启动时,先prepare() new出来一个Looper,并且把它塞到ThreadLocal里面,以后在同一个线程要用的时候都从里面拿,避免创建多个Looper,然后就开始了loop(),死循环之路,也就是说程序无时无刻不在loop(),然后msg=null的时候,return,直到发现有了msg,msg.target.dispatchMessage(msg);交给msg的target,也就是handler来处理。

我们再来看下Handler的源码,我们先看Handler的构造函数

    public Handler(Callback callback, boolean async) {
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
    }

Looper.myLooper,正是我们刚才说的,从ThreadLocal里面拿出本线程已有的Looper,然后MessageQueue,也是原来Looper里面的那个MessageQueue,接下来是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) {
        return queue.enqueueMessage(msg, uptimeMillis);
}

不难理解,Handler并没有真正意义的去“发送”,而是把消息放到了MessageQueue中而已。

最后,我们来看下Handler如何处理的消息,dispatchMessage

    public void handleMessage(Message msg) {
    }
    /**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
            handleMessage(msg);
    }

还记不记得,Loop.loop()中,一旦发现MessageQueue有值,就会调用msg.target.dispatchMessage(msg);走的就是这里啦,还记不记得我们平时写Handler的时候,一般都是这样

     Handler mHandler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
            
            }
        };

重写的就是上面这个方法啦,至此,我们来回顾一下上面三个问题:

1.Looper是个什么玩意,它是怎么创建的?它是什么时候开始循环的?

2.Handler是怎么发送消息让Looper知道的?

3.Looper又是怎样取出消息且回调给Handler来处理的?

如果对照源码仔细看了本文,相信这几个问题已经不难啦,而且你也学会了如何真正的阅读源码,那就是抓住主线而忽略掉不重要的部分,如果对你有帮助,点个喜欢吧!

你可能感兴趣的:(Handler机制到底是个什么东西?(一句话说清楚))