美文网首页
Handler机制小结

Handler机制小结

作者: 橘座大人 | 来源:发表于2018-10-24 18:58 被阅读0次

    Handler笔记

    什么是handler机制?
    handler机制的主要成员
    1、handler:负责发送处理消息
    2、message:消息的信息的载体
    3、messageQueue:存放message的队列
    4、looper:handler机制的动力,无限循环的从messageQueue队列中取出message给handler

    图1

    1、Handler

    (1)我们先来看看handler的构造方法

          public Handler() {
            this(null, false);
        }
        
         public Handler(Callback callback, boolean async) {
            if (FIND_POTENTIAL_LEAKS) {
                final Class<? extends Handler> klass = getClass();
                if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                        (klass.getModifiers() & Modifier.STATIC) == 0) {
                    Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                        klass.getCanonicalName());
                }
            }
    
            mLooper = Looper.myLooper();
            if (mLooper == null) {
                throw new RuntimeException(
                    "Can't create handler inside thread that has not called Looper.prepare()");
            }
            mQueue = mLooper.mQueue;
            mCallback = callback;
            mAsynchronous = async;
        }
    

    (2)默认的构造方法走了 Handler(Callback callback, boolean async) 构造方法,此方法用 mLooper = Looper.myLooper();获取了looper,然后又用looper创建了messageQueue

    2、Looper

    在Looper类中

        /**
         * Return the Looper object associated with the current thread.  Returns
         * null if the calling thread is not associated with a Looper.
         */
        public static @Nullable Looper myLooper() {
            return sThreadLocal.get();
        }  
    

    注意上面的注释 返回一个与当前线程关联的Looper对象
    那Looper是怎么创建的呢,既然有get方法,那应该就有set方法。搜索sThreadLocal.set,果然找到了

     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));
        }
    

    说明prepare方法直接创建了一个当前线程的Looper

    在UI主线程中,会默认的创建好Looper对象,而在子线程中要使用本线程的Handler需要手动创建Looper对象,如下

    class LooperThread extends Thread {
            public Handler mHandler;
    
            public void run() {
                Looper.prepare();
    
                mHandler = new Handler() {
                    public void handleMessage(Message msg) {
                        
                    }
                };
    
                Looper.loop();
            }
        }   
    

    3、MessageQueue

    在handler中我们知道MessageQueue对象通过
    mQueue = mLooper.mQueue;
    其中的消息是怎么来的呢我们我们通过handler的sendMessage()方法来进行分析

    public final boolean sendMessage(Message msg)
       {
           return sendMessageDelayed(msg, 0);
       }  
    

    handler的sendMessage()方法又调用了

     public final boolean sendMessageDelayed(Message msg, long delayMillis)
        {
            if (delayMillis < 0) {
                delayMillis = 0;
            }
            return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
        }
    

    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);
        }
    

    此方法先获取了全局的messageQueue对象mQueue最后通过MessageQueue.enqueueMessage()将message存到了messageQueue队列中

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
            msg.target = this;
            if (mAsynchronous) {
                msg.setAsynchronous(true);
            }
            return queue.enqueueMessage(msg, uptimeMillis);
        }
    
    通过上面的分析我们知道了messageQueue是怎么进数据的,后边我们分析一下怎么从里面取数据

    我们在子线程中使用Handler的示例中最后一步 调用Looper.loop();然后我们来看看

        public static void loop() {
            final Looper me = myLooper();
            ······
            for (;;) {
                Message msg = queue.next(); // might block
                ······
                 try {
                    msg.target.dispatchMessage(msg);
                    end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
                } finally {
                    if (traceTag != 0) {
                        Trace.traceEnd(traceTag);
                    }
                }
                ······
            }
        }
    
    

    在Looper.loop();方法中我们可以看到for循环中从queue中取出message,然后message是怎么给到handler呢?
    在msg.target.dispatchMessage(msg);这一步中我们先看看target是个什么?转到message类中会发现

    /*package*/ Handler target;
    

    target是个handler实例 由此可以得出整个message的传播回路

    总结:

    在一个线程中创建handler、looper、messageQueue
    handler把带有信息的message通过sendmessage()发送给messageQueue队列,然后looper通过Looper.loop()无限循环从messageQueue中取出message,然后在发送给handler,handler在handleMessage()方法中处理信息

    最后感谢前人的好文章的指导,个人根据个人的理解总结如有不对的地方,请留言。
    https://blog.csdn.net/reakingf/article/details/52054598
    https://blog.csdn.net/pgg_cold/article/details/79400435?utm_source=blogxgwz2
    https://blog.csdn.net/qian520ao/article/details/78262289?locationNum=2&fps=1
    https://blog.csdn.net/qq_32770809/article/details/79132363?utm_source=blogxgwz1

    相关文章

      网友评论

          本文标题:Handler机制小结

          本文链接:https://www.haomeiwen.com/subject/zvwxtqtx.html