美文网首页
2018-07-11

2018-07-11

作者: TRT131 | 来源:发表于2018-07-11 14:23 被阅读0次

    Handler机制实现线程间通信

    • 如何实现
      通过send或post方法将message提交到当前handle所在线程的MessageQueue中,当前线程关联的Looper不断循环在messageQueue中取出message
      msg.target.dispatchMessage(msg);
      分发给对应的handler消耗

    • Looper是什么
      我们通过Looper().prepare()给当前线程设置一个Looper,其关联函数如下

    public static void prepare() {
            prepare(true);
        }
    
        private static void prepare(boolean quitAllowed) {
        //用以判断当前线程是否已创建Looper
            if (sThreadLocal.get() != null) {
                throw new RuntimeException("Only one Looper may be created per thread");
            }
        //新建Looper对象与当前线程绑定
            sThreadLocal.set(new Looper(quitAllowed));
        }
    private Looper(boolean quitAllowed) {
      //一个Looper对象管理一个MessageQueue对象
            mQueue = new MessageQueue(quitAllowed);
      //获取当前Thread对象
            mThread = Thread.currentThread();
        }
    

    执行完Looper().prepare()后就为该线程创建了一个与之绑定的Looper对象,并且有一个受该Looper管理的MessageQueue,作为message的容器。

    new Thread(
                            new Runnable() {
                        @Override
                        public void run() {
                            Looper.prepare();
                            handler.sendEmptyMessage(0x123);
                            Looper.loop();
                        }
                    })
    

    可以看到prerare()后还有一个loop()函数

    public static void loop() {
          //获得Looper对象
            final Looper me = myLooper();
            if (me == null) {
                throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
            }
        //得到该Looper对象管理的MessageQueue
            final MessageQueue queue = me.mQueue;
            Binder.clearCallingIdentity();
            final long ident = Binder.clearCallingIdentity();
        //执行循环操作,通过next()得到queue中的message分发到handler中,可能会堵塞
            for (;;) {
                Message msg = queue.next(); // might block
                if (msg == null) {
                    // No message indicates that the message queue is quitting.
                    return;
                }
    //这里的target就是handler对象
               msg.target.dispatchMessage(msg);
                if (ident != newIdent) {
                    Log.wtf(TAG, "Thread identity changed from 0x"
                            + Long.toHexString(ident) + " to 0x"
                            + Long.toHexString(newIdent) + " while dispatching to "
                            + msg.target.getClass().getName() + " "
                            + msg.callback + " what=" + msg.what);
                }
    //设置message处理完毕
                msg.recycleUnchecked();
            }
        }
    

    loop()函数会开启循环,将MessageQueue中的message分配出去进行处理

    • Handler发出message与处理
        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());
                }
            }
      //获得当前线程的Looper对象
            mLooper = Looper.myLooper();
            if (mLooper == null) {
                throw new RuntimeException(
                    "Can't create handler inside thread that has not called Looper.prepare()");
            }
    //取出MessageQueue对象
            mQueue = mLooper.mQueue;
            mCallback = callback;
            mAsynchronous = async;
        }
    

    在线程中创建handler时,我们就已经给handler对象传递了当前线程对应的唯一的MessageQueue

    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
      //获取该handler所在线程的MessageQueue
            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赋值
            msg.target = this;
            if (mAsynchronous) {
                msg.setAsynchronous(true);
            }
            return queue.enqueueMessage(msg, uptimeMillis);
        }
    

    到这里,我们就给将 message加入到handler所在线程对应的MessageQueue中,并且指定了处理message的handler。

    ///Loop()方法中调用此方法,执行对message的处理
    public void dispatchMessage(Message msg) {
            if (msg.callback != null) {
                handleCallback(msg);
            } else {
                if (mCallback != null) {
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                handleMessage(msg);
            }
        }
    
    一个线程只能有一个Looper,且只能有一个MessageQueue,但是可以绑定多个handler处理不同事件

    HandlerThread

    继承自Thread,自身带有一个Looper对象,可用来新建handler。一般用来执行耗时操作,与自定义Thread再执行Looper.prepare()效果相同。

    相关文章

      网友评论

          本文标题:2018-07-11

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