• 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 原理图

    在 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
    • 进入无限循环

      //进入无限循环
          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()插入到消息队列。

  • 相关阅读:
    如何编译Linux内核
    linux启动过程
    linux ifconfig
    Android 4.0 x86安装教程 附带联网参数详细设置
    linux ntfs模块
    Java 入门进阶
    深入理解Java中的String
    Java中字符串string的数据类型
    IDEA设置JVM运行参数
    Java11实战:模块化的 Netty RPC 服务项目
  • 原文地址:https://www.cnblogs.com/jiy-for-you/p/7281998.html
Copyright © 2020-2023  润新知