Android中消息循环

目录

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 sThreadLocal = new ThreadLocal();

存放过程是

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中消息循环)