美文网首页
Android中消息循环

Android中消息循环

作者: e小e | 来源:发表于2020-04-08 19:45 被阅读0次

    目录

    1,handler消息循环机制

    2,post和sendMessage区别


    1,handler消息循环机制

    Android中的线程之前要通讯,通常使用的是Handler机制进行通讯,我们开启一个线程通常是不具备线程之间的通讯能力的,想让它具备通讯能力需要在线程中启动Looper,如下

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

    这个时候我们可以通过在别的线程关联到LooperThread的looper并实例化Handler进行消息的发送.

    * Use the provided {@link Looper} instead of the default one.
    *
    * @param looper The looper, must not be null.
    */
    public Handler(Looper looper) {
            this(looper, null, false);
    }
    

    那它的基本原理是什么呢?
    我们先来看看prepare是怎么实现

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

    这里会去实例化一个Looper对象,放入sThreadLocal, sThreadLocal的声明是

    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    

    存放过程是

    public void set(T value) {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
    }
    

    这里可以看到,我们通过当前线程去获取Thread中

    Thread {
         //代码省略...
         ThreadLocal.ThreadLocalMap threadLocals = null;
         //代码省略...
    }
    

    通常来说第一次调用都是null,所以会走createMap(t, value)

    void createMap(Thread t, T firstValue) {
            t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
    

    createMap直接就会创建ThreadLocalMap,并传入刚才的Looper对象,并放入到了线程的threadLocals中了.
    这里需要说明一点是每个Thread都有一个 ThreadLocal.ThreadLocalMap threadLocals,它是一个独立的线程存储空间. 在消息循环机制中用来存放Looper对象. 大致模型图如下


    image.png

    接下来我们会在loop()中去启动消息循环机制

    public static void loop() {
          //代码省略...
            final Looper me = myLooper();
            final MessageQueue queue = me.mQueue;
            for (;;) {
                Message msg = queue.next(); // might block
                msg.target.dispatchMessage(msg);
            }
          //代码省略...
    }
    

    这样就进入了一个循环,会不停的接收queue中的消息,并分发到Message中的target对象上,这里的target是发送消息的Handler.
    我们可以看一个发送消息的例子

    val handler = Handler()
    handler.sendMessage(Message())
    
    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }
    
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
          if (delayMillis < 0) {
                delayMillis = 0;
          }
          return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
    
    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);
    }
    

    这里msg.target = this实际上就是Handler对象,所以调用的msg.target.dispatchMessage(msg)实际上也是调用到的Handler的dispatchMessage

    public void dispatchMessage(Message msg) {
            if (msg.callback != null) {
                handleCallback(msg);
            } else {
                if (mCallback != null) {
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                handleMessage(msg);
            }
    }
    
    2,post和sendMessage区别

    在使用Handler发送消息的过程中,通常会有两种调用方式,一种是post一个Runnable另外就是sendMessage, 这两种调用本质区别是什么呢. sendMessage调用实际上上面已经说过,最终会走到dispatchMessage的handleMessage处理消息,这里handleMessage有两种情况,一个是mCallback的handleMessage,mCallback是外部传入的Callback,通常实例化Handler的时候会传

    val handler = Handler(Handler.Callback {
           TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    })
    

    下面handleMessage(msg)就需要继承Handler进行handleMessage重写处理了.
    下面来看看post的情况

    public final boolean post(Runnable r)
    {
           return  sendMessageDelayed(getPostMessage(r), 0);
    }
    
    private static Message getPostMessage(Runnable r) {
            Message m = Message.obtain();
            m.callback = r;
            return m;
    }
    

    这里m.callback = r 实际上在dispatchMessage中就会调用

    if (msg.callback != null) {
        handleCallback(msg);
    }
    

    这里处理

    private static void handleCallback(Message message) {
            message.callback.run();
    }
    

    到这就会直接执行掉这个Runnable对象。所以结论就是,post是发送一个带有callback(实际上是Runnable对象),然后在接收消息的线程直接执行掉,而sendMessage是发送一个消息,接收消息的线程收到后会根据消息内容进行相应的处理逻辑.

    相关文章

      网友评论

          本文标题:Android中消息循环

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