源码--->Handler的初步认识

关于看源码

其实我还是很喜欢看别人的想法来对照自己的,但是看不看并不重要我觉得。别人的代码完全淹没掉自己的想法,然后失去自己的想法,遇到问题只能去找别人的方法解决,失去了自己。
当然,别人解决问题的方法,我们当然有必要看,但是完全没必要一字一句去研究,因为他的代码中想必只有20%的地方是思想,80%只是为了解决各种小问题。
尤其是今天看到一个关于handler如何使用不发生内存泄漏的文章,感受颇深。https://blog.csdn.net/alcoholdi/article/details/54948058

入口1 ----Handler handler = new Handler()

打开盒子

①使用了两个参数的构造函数

    public Handler() {
        this(null, false);
    }
转到两个参数的构造函数处

①得到轮询器looper
②得到队列queue
③其余暂时略过

    public Handler(Callback callback, boolean async) {
        //省略
        mLooper = Looper.myLooper();
        mQueue = mLooper.mQueue;
        //省略
    }
进入Looper.myLooper()

①发现一个新的类SThreadLocal.get()得到轮询器looper

    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }
进入sThreadLocal.get()

①Thread t = Thread.currentThread();看看哪个线程创建的handler。
②ThreadLocalMap map = getMap(t);有一个map存的是looper。
③map.getEntry(this);这里的this是ThreadLoca类,根据threadLocal得到looper,然后返回。
④我们明白了:哪个线程创建的handler,它所使用的looper就是哪个线程的。

    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                T result = (T)e.value;
                return result;
            }
        }
        //省略
    }
出口

①每一个线程对应了一个轮询器。
②哪个线程创建的handler,handler就持有的是哪个线程的looper。
③每个looper里面自带一个队列。

入口2 ----handler.sendEmptyMessage(0);

打开盒子
    public final boolean sendEmptyMessage(int what)
    {
        return sendEmptyMessageDelayed(what, 0);
    }
    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        //略
        return sendMessageDelayed(msg, delayMillis);
    }  
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        //略
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        //略
        return enqueueMessage(queue, msg, uptimeMillis);
    }
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        //略
        return queue.enqueueMessage(msg, uptimeMillis);
    }
    boolean enqueueMessage(Message msg, long when) {

        synchronized (this) {
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }
        }
        return true;
    }
关闭盒子

①经历了很多步骤终于要加入队列了。
②一套操作终于把msg接上去了,看到next,是不是有点熟悉。

入口3----疑问

①事件怎么可以无限执行的。

②消息是怎么被无限取出来的。

③怎么在没有消息的时候阻塞的。

looper中的loop函数中出现了for(;;)

①发现这个函数调用了queue.next();
②出现了分发消息的事件。

    /**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    public static void loop() {
        //略
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                return;
            }
            try {
                msg.target.dispatchMessage(msg);
            } finally {
            }
        }
        //略  
    }

①原来message的target是handler;

public final class Message implements Parcelable {
    /*package*/ Handler target;
}

①熟悉的handlerMessage这个正是我们复写的函数。

    public void dispatchMessage(Message msg) {
        //略
        handleMessage(msg);
    }
于是来到了MessageQueue的queue.next();

①抛弃别的东西,我们看到它返回一个msg,msg中间怎么得到的略过。
②我们看到它有一个native方法。

    Message next() {
        for (;;) {
            //略
            nativePollOnce(ptr, nextPollTimeoutMillis);
            //略
            synchronized (this) {
                Message msg = mMessages;
                //略
                return msg;
            }
            //略
        }
    }
来到出口处思考一下
答案①:looper里面的轮询一直在向queue索要消息,拿到消息就执行。执行完了继续索要消息。
????没拿到消息就结束,但是我们不能让它结束,还要靠他执行消息呢。
答案②:为了能够不让looper终止,所以queue必须要每次都给looper消息。所以没消息他自己要阻塞等待,阻塞必然就在他里面。
答案③:阻塞必然是在它里面,那么我们来看看这个可疑的方法,百度一下nativePollOnce。
无标题.png
看到这里就放心了,就是它实现了阻塞。不过我们暂时还是不去想它了,暂且记住它(๑╹◡╹)ノ"""。

总结

①每一个线程对应了一个轮询器。
②哪个线程创建的handler,handler就持有的是哪个线程的looper。
③每个looper里面自带一个队列。
④looper执行完就朝queue要消息,queue自己有了消息以后,马上return给looper,looper执行完了,继续要,不断循环。
⑤一个奇妙的native阻塞,实现了等待队列中有消息的效果,同时又不阻塞当前线程。
⑥以上所有内容仅是个人理解,不一定准确。

你可能感兴趣的:(源码--->Handler的初步认识)