当前位置: 首页 > news >正文

Android Handler的机制跟源码分析

一、消息机制

        在应用启动时,会执行 main() 方法, main() 会创建一个 Looper 对象,然后开启一个死循环,目的是不断从 消息队列  MessageQueue 里面取出 Message 对象并处理。

        在Android中使用消息机制,会优先想到的是Handler。Handler可以轻松的将一个任务切换到Handler所在的线程去执行。在多线程的应用场景中,可以将工作线程中需要更新UI的操作信息传递到主线程去执行,从而实现工作线程更新UI的操作,最终实现异步消息的处理。

二. Handler机制模型

消息机制主要包含Handler、Message、MessageQueue,Looper这四个类。

  • Handler:消息辅助类。主要功能将 Message 对象发送到 MessageQueue 中,同时将自己的引用赋值给 Message#target (Handler.sendMessage())。也可以实现 handleMessage() 方法处理回调。

  • Message:消息实体。需要传递的消息也可以传递数据。

  • MessageQueue:消息队列。**内部实现并不是队列,而是利用单链表去实现因为在插入和删除数据有优势。**用于存储Handler发给来的消息( Message )以及取出。 内部使用单链表实现 

  • Looper:与线程绑定,不止局限于主线程,绑定的线程来处理 Message 。不断循环执行 Looper.loop() ,从 MessageQueue 中读取 Message ,按分发机制将消息分发出去给目标处理(将 Message 发到 Handler.dispatchMessage 方法去处理)。

三、Handler运行流程

工作流程: 异步通信准备==>消息入队==>消息循环==>消息处理

1.异步通信准备

假定在主线程创建Handler,则会直接在主线程中创建 Looper , MessageQueue 和 Handler 对象。Looper和MessageQueue对象均属于其 创建线程 (由主线程创建则属于主线程)。创建 Looper 时会自动创建 MessageQueue 对象,创建好 MessageQueue 对象后, Looper 自动进入循环。 Handler 自动绑定 Looper 以及 MessageQueue 。

 Looper 对象的创建方法一般通过 Looper.prepareMainLooper() 和 Looper.prepare() 方法。

2.消息入队

工作线程通过 Handler 发送 Message 到 MessageQueue 中。消息内容一般是UI操作,通过 Handler.sendMessage(Message message) 或 Handler.post(Runable r) 发送。加入 MessageQueue 一般通过 MessageQueue.enqueueMessage(Message msg,long when) 操作。

3.消息循环

分为消息出队和消息分发两个步骤

  • 消息出队: Looper 从 MessageQueue 中循环取出 Message 

  • 消息分发: Looper 将取出的 Message 分发给创建消息的 Handler 

消息循环过程中, MessageQueue 为空,则线程堵塞

4.消息处理

 Handler 接受发过来的 Message 并处理。

四、Handler源码解析

1. 创建循环器对象( Looper )和创建消息队列对象( MessageQueue )

创建Looper对象主要有两个方法: Looper.prepareMainLooper() 和 Looper.prepare() 

创建MessageQueue对象方法:创建Looper对象时会自动创建MessageQueue

// 源码位置:../core/java/android/os/Looper.java
 
final MessageQueue mQueue;
final Thread mThread;
//Looper对象创建时会自动创建一个MessageQueue对象。
private Looper(boolean quitAllowed) {
     mQueue = new MessageQueue(quitAllowed);
     mThread = Thread.currentThread();
    }
 
//为当前线程(子线程)创建一个Looper对象 需要在子线程中主动调用该方法
public static void prepare() {
        prepare(true);
    }
 
private static void prepare(boolean quitAllowed) {
    //判断sThreadLocal是否为null,不为空则直接跑出异常 可以保证一个线程只可以调用一次prepare方法
    if (sThreadLocal.get() != null) {
          throw new RuntimeException("Only one Looper may be created per thread");
       }
    sThreadLocal.set(new Looper(quitAllowed));
    }
 
//为主线程创建一个Looper对象 该方法会在主线程创建时自动调用
public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

    1. 创建Looper对象时会自动创建MessageQueue对象

    2.主线程的Looper对象是自动生成的,而子线程需要调用Looper.prepare()创建Looper对象

    创建主线程是调用了ActivityThreadmain()方法。

    然后按照流程调用了Looper.prepareMainLooper()Looper.loop()。所以主线程不需要调用代码生成

    Looper对象。

    3.Handler的主要作用是( 在主线程更新UI ),所以Handler主要是在主线程创建的。

    4.Looper与Thread是通过 ThreadLocal 关联的。由于 ThreadLocal 是与线程直接关联的,

    参考 prepare() 。

    5.子线程创建Handler对象:无法在子线程直接调用Handler无参构造方法Handler创建时需要绑定Looper对象 。需要使用 HandlerThread 。

    //源码位置: ../core/java/android/app/ActivityThread.java
     public static void main(String[] args) {
         ...
          Looper.prepareMainLooper();
          Looper.loop();
         ...
     }

    2.开启Looper即消息循环

            创建了 Looper和MessageQueue 

    相关文章:

  1. Android 系统面试问题
  2. MySQL主从同步+binlog
  3. 同为科技智能PDU助力Deepseek人工智能和数据交互的快速发展
  4. 【python】简单的flask做页面。一组字母组成的所有单词。这里的输入是一组字母,而输出是所有可能得字母组成的单词列表
  5. 21道关于Vue3的面试题及其解析
  6. Linux学习笔记18---串口格式化函数移植实验
  7. langchain学习笔记之小样本提示词Few-shot Prompt Template
  8. 19.3 连接数据库
  9. stm32点灯 GPIO的输出模式
  10. 开源的轻量级分布式文件系统FastDFS
  11. 土星云边缘计算微服务器 SE110S-WA32加持DeepSeek,本地部署企业私有推理大模型!
  12. Ubuntu安装geteck/jetlinks实战:源码启动
  13. 热更图片方案
  14. 深入解析:如何在C#和C/C++之间安全高效地通过P/Invoke传递多维数组
  15. APNs证书添加到Trust Store (信任库)
  16. Excel中不用复杂公式根据指定X列的数值N复制整行数据N行简单方法
  17. leetcode 543. 二叉树的直径
  18. 基于SpringBoot的宠物健康顾问管理系统
  19. DeepSeek 本地部署及深度使用
  20. 本地部署【LLM-deepseek】大模型 ollama+deepseek/conda(python)+openwebui/docker+openwebui
  21. 中国国家电影局与俄罗斯文化部签署电影合作文件
  22. 绿城约13.93亿元竞得西安浐灞国际港港务片区地块,区内土地楼面单价首次冲破万元
  23. 西安碑林博物馆票价将调至85元,工作人员:10元属于改扩建期间惠民票
  24. 明查|这是“C919迫降在农田”?实为飞机模型将用于科普体验
  25. 中国证监会印发《推动公募基金高质量发展行动方案》
  26. 中国难以承受高关税压力?外交部:任何外部冲击都改变不了中国经济基本面