Android 消息队列机制

在非UI线程使用Handler进行线程通信时,一般都需要进行3个步骤:

  • 创建Looper Looper.prepar()
  • 创建Handler
  • 启动消息循环Looper.loop()

通过这3步,基本就建立好了 Android 的多线程消息通信机制:

  • Handler
  • MessageQueue
  • Looper
  • Message

这几者可谓是你中有我,我中有你的存在。通过 Handler 发送 Message 到 Looper 的 MessageQueue 中,待 Looper 的循环执行到 Message 后,就会根据 Message 的 target handler,回调对应 Handler 的 handlerMessage 方法。

例如: Thread-A 拥有一个 Looper,Thread-B 持有一个在 Thread-A 中构造的 Handler,Thread-B 就可以通过这个 Handler 将 Message 发送到 Thread-A 的 Looper 的 MessageQueue 中,然后消息会走到 Thread-A 的 Handler 的 handleMessage 方法。

Looper 原理图

28744549.jpg

在 Looper 类加载时就会创建一个 ThreadLocal 类型的类变量 sThreadLocal

public final class Looper {
    private static final String TAG = "Looper";

    // sThreadLocal.get() will return null unless you've called prepare().
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

Looper.prepar()

public static void prepare() {
    prepare(true);
}

private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    // 将构造的 looper 存到类变量 sThreadLocal 中
    sThreadLocal.set(new Looper(quitAllowed));
}

private Looper(boolean quitAllowed) {
    // 构建一个 messageQueue 成员
    mQueue = new MessageQueue(quitAllowed);
    // 将当前线程存入 mThread 中
    mThread = Thread.currentThread();
}

在这里面主要执行了 3 步:

  • 构建一个 looper
    • 构建一个 messageQueue 成员
    • 将当前线程存入 mThread 中
  • 将构造的 looper 存到类变量 sThreadLocal 中

至此,执行 Looper.praper 的当前线程就会拥有一个 looper 成员了,存放在 Looper 的 sThreadLocal 中。

创建Handler

public Handler(Callback callback, boolean async) {
    ...
    // 通过`Looper.myLooper()` 类方法获取 sThreadLocal 中储存的当前线程的 looper,将这个 looper 绑定到 handler 的成员变量 mLooper 中
    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");
    }
    // 将 mLooper 中的 messageQueue 绑定到 handler 的成员变量 mQueue 中
    mQueue = mLooper.mQueue;
    ...
}
public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

Looper.loop()

  • 声明一个局部常量final Loop me = myLoop()
    • myLoop()将返回当前线程的looper成员
  • 声明一个局部常量final MessageQueue queue
    • 将me.mQueue赋值给queue
  • 进入无限循环
    ```java
    //进入无限循环
    for (;;) {
    //取出一条消息
    Message msg = queue.next();
    //没有消息就阻塞
    if (msg == null) {
    return;
    }
    ...

          //分发消息
          try {
              msg.target.dispatchMessage(msg);
              //msg.target是一个Handler对象
          } finally {
              if (traceTag != 0) {
                  Trace.traceEnd(traceTag);
              }
          }
          ...
    
          //回收消息
          msg.recycleUnchecked();

    ```

  • 通过Message.obtain()获取的消息,需要使用Handler.sendMessage()插入到消息队列。
  • 通过Handler.obtainMessage()获取的消息,可以使用message.sendToTaget()插入到消息队列。

转载于:https://www.cnblogs.com/jiy-for-you/p/7281998.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值