Handler源码流程梳理

Handler机制(一)——Handler运行流程分析 Handler运行机制 阅读详情

Handler的工作流程

 

需要搞明白Handler的流程,就是从sendMessage一直到handleMessage的过程。

 

Handler.sendMessage()

首先来看sendMessage,从图中就可以看出来,它就是把货物放到了这个传送带上来。

在Handler.java这个类里面,有很多函数用来发送消息。其中send开头的就有这些:

然后还有post开头的:

也就是说在这个类里面,就有这么多的函数用来发送消息的。它们之间有什么关系呢?

看这个图,也就是说任意一个send,无论它的流程怎么跑,最后它都会调度在了enqueueMessgae这个方法中。

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

而Handler.enqueueMessage()又调用了MessageQueue.enqueueMessage(),所以,这一系列的函数,最终的目的都是在消息队列中添加了消息。

 

MessageQueue.enqueueMessage()

在enqueueMessage()中,它维持了一个消息队列,这个消息队列其实是一个优先级队列。

优先级队列

假如有一个M4要插入到这个队列中去,它首先要轮训M1-M2-M3这个队列;

然后分别比较M4与M1、M2、M3...;

看到M4刚好比M2大,且比M3小,就插入到这个队列中去,这个队列也就是个有序的队列

在源码里面,MessageQueue.java中的enqueueMessage方法里面有一个for循环,他的作用就是根据时间when进行一个排序。

                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }

看这个for循环,就是对单链表的一个轮询,其关键点就在于找到循环中的break。

enqueueMessage(Message msg, long when)

when是传入的值,代表这个消息什么时候被执行,如果when等于0,那就是立刻执行。

首先,它会拿到第一个节点p。

p = p.next;

将第一个节点的时刻p.when,与我们刚加入的这个消息的时刻when对比。

when < p.when

如果新加入的消息的时刻小于前一个节点的时刻,那么新加入的消息就要比前一个节点的消息先执行,那么,新加入的消息就要插入到这个消息的之前,所以就执行break停止查找,然后就将消息插入到前面。

msg.next = p;

它沿着这个序列进行轮询,先查询第一个消息的执行时间,如果第一个消息的执行时间早于新插入的这个消息的节点,再去查找第二个节点,这时候发现第二个消息的发送的时间又比这个时间早,他就会再去查找第三个,他发现第三个消息的执行时间要比插入的消息的执行时间晚,这时候,就可以把这个消息插入到了这个消息的队列中来,这样就形成了一个按照时间先后进行排序的有序队列。

但我们添加的消息基本上是不相同的,除非是0。

因为在sendMessageDelayed中,它的延迟时间是系统时间加上delay的时间,而系统时间是每时每刻都在增大的,就像是for循环每走一遍,他的时间也会增大。

    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

而如果等于0,则直接插入。

            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            }

 

MessageQueue.next()

前面说到往MessageQueue这个消息队列中存消息,就一定会有从这个消息队列中取消息,next()函数就是返回了一个Message。

    Message next(){
        ....
    }

next()函数是如何取的消息,要先看下这个if语句。

                    //开机到现在的毫秒数如果小于msg.when则代表还未到发送消息的时间
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        // 虽然有消息,但是还没有到运行的时候
                        //计算还有等待多久,并赋值给nextPollTimeoutMillis
                    	//设置下一次查询消息需要等待的时长
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                    	//代表当前没有阻塞
                        mBlocked = false;
                     // 获取msg并且删除该节点 
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        //返回拿到的消息
                        return msg;
                    }

他先用 当前时刻now 和 它所拿到的队头的时刻msg.when 进行对比,now < msg.when 也就是说,消息队列的第一个节点还没到可以执行的时刻,所以就wait等待。

反之,如果 now >= msg.when ,说明现在的时刻已经到了可以发送消息的时刻,就可以把消息返回出去。

 

Looper.loop()

有没有想过这样一个问题:上面所说的next()函数由谁来调用的呢?

对,就是这个loop()函数,它不断的调用next()函数,通过调用next()函数去轮询我们的MessageQueue,让这个MessageQueue这样一个传送带滚动起来的。

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

           ......
        }

如果这个消息队列为空的时候,会等待(MessageQueue.next())。

        for (;;) {

            .....

            //native的方法,在没有消息的时候回阻塞管道读取端,只有nativePollOnce返回之后才能往下执行
            //阻塞操作,等待nextPollTimeoutMillis时长
            nativePollOnce(ptr, nextPollTimeoutMillis);

            .....

        }

所以它就一直会block在这里(Looper.loop())。

Message msg = queue.next(); // might block

被block之后就不会走return,不会走return,这个for循环(死循环)就一直在这里等待。

当Looper获取到了这个消息之后,就会调用dispatchMessage这个函数。

                msg.target.dispatchMessage(msg);

而dispatchMessage又会调用Handler.dispatchMessage()来处理消息,这时候就完成了消息链条的整个流程。

    /**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

 

handler全解 handler一,handler简介及其使用场景(1)handler简介(2)handler使用场景二,handler工作原理分析(1)handler工作流程(2)Message(3)Messagequeue1-普通消息2-同步屏障与异步消息3-阻塞与唤醒(pipe/epoll机制)(4)Looper1-ThreadLocal机制(5)IdleHandler介绍与使用场景一,handler常见问题分析(1)内存泄露问题(2)非ui线程操作view(3)View.post与handler.post的区别 一, 阅读详情

相关推荐

Android Handler 机制从底层原理到实战应用的深度彻底解析

本文深入解析Android的Handler机制,包括其核心组成、执行流程和底层原理。Handler是Android进程内线程间通信的核心机制,由Looper、MessageQueue、Handler和Message四大组件构成,实现线程间任务调度和UI更新。主线程的Looper由系统自动创建,子线程需手动调用Looper.prepare()和loop()。文章详细分析了消息发送、入队、循环和处理的全流程,解释了Looper.loop()死循环不会阻塞主线程的原因(基于Linux管道+epoll机制)。同时探

fuge2008的博客 1427

android Handler机制

handler机制

anhuilee的博客 1000

Android校招笔试题复盘:从Handler到MVVM的核心考点解析

Android开发中,掌握底层通信与架构设计是进阶的基石。Handler消息循环机制通过epoll阻塞实现高效线程调度,而Binder借助mmap完成一次拷贝的跨进程通信,两者共同构成了系统流畅运行的骨架。随着技术演进,MVVM架构通过ViewModel与LiveData实现UI与业务逻辑解耦,配合RecyclerView的缓存复用机制,能够显著提升复杂页面的性能表现。在校招与社招面试中,这些知识点常以笔试题形式出现,不仅考察API使用,更关注源码原理与工程实践。本文以一套经典校招笔试为蓝本,系统梳理Act

weixin_34184158的博客 381

Handler消息机制-Handler

Handler 消息处理机制主要由 Handler、Looper、MessageQueue 和 Message 四部分组成。Handler作用:用于发送消息和处理消息。发送消息到 MessageQueue。处理从 Looper 分发的消息。特点:每个 Handler 绑定到一个 Looper,从而绑定到一个线程。可以发送 Message 或 Runnable。Message作用:消息的载体,封装了需要处理的任务或数据。通过 what 字段标识消息类型。通过 obj 字段传递数据。

只想搞钱 1719

从时序博弈到数据稳定:CS1237驱动中的信号滤波与卡尔曼实践

本文探讨了CS1237高精度ADC驱动在复杂工业环境中的信号处理挑战,重点介绍了一阶滤波与自适应卡尔曼滤波算法的实践应用。通过参数优化和动态调整策略,有效提升了数据稳定性和抗干扰能力,为嵌入式系统在噪声环境下的精密测量提供了可靠解决方案。

rnn9storyteller的博客 864

Seedance2.5本地部署指南:从环境配置到生产优化的完整实践

在 AI 内容生成领域,本地部署方案正逐渐成为开发者和技术团队关注的焦点。Seedance2.5 作为一款支持图像和视频生成的 AI 工具,其完全离线运行的能力解决了云端服务在数据隐私、使用成本和访问稳定性方面的痛点。对于需要处理敏感内容、频繁生成素材或希望完全掌控生成流程的技术人员来说,掌握本地部署方法具有实际价值。 本文将以 Seedance2.5 的本地部署为例,详细介绍从环境准备、依赖配置到运行验证的完整流程,同时深入分析关键参数配置、常见问题排查方法以及生产环境下的优化建议。通过实际部署过程,理解

weixin_33139275的博客 732

Handle消息机制

Handle 消息机制

weixin_43836998的博客 838

APM无人船测绘实战:从RTK、测深仪到图传的完整系统集成指南

本文提供了一套完整的APM无人船测绘系统集成实战指南。从RTK模块配置、测深仪数据同步到图传系统接入,详细解析了硬件选型、接线、软件参数调试及QGC地面站任务规划的全流程,旨在帮助用户将分散的部件整合为可自主执行水下地形测绘的可靠工具。

rr23456的博客 521

Handler机制流程梳理、源码分析

Handler机制流程梳理、源码分析 Handler机制的相关类 Looper与MessageQueue Message Handler

linghuanyun的博客 620

【杰理AC696X】ADKEY复用指示灯不定时出现灯不亮或按键失灵的问题

测试SDK版本:《ac696n_soundbox_sdk_v1.5.0-20211217》ADKEY复用指示灯的做法多用于蓝牙小音箱,IC引脚越来越少,复用也就用的越多了,不过,在使用前应评估好功能,因为复用的做法,肯定会牺牲点东西的,如果体验感啥的。 比如这个图,(V-)按键按下时,LED是会一直导通发光的,按不同阻值的按键还有亮度不一致的问题,这样的问题有的客户是不接受的,这就要另寻他法了。某天调好案子,放在一边测试时,发现指示灯不亮了,按键也不起作用,想起之前AC692系列也有类似的问题,很快就定位到

xx842678的博客 1656

嵌入式开发环境Vscode开发STM32单片机程序

STM32单片机非常强大,大多数教程都是使用 keil 编译器,keil 是收费的而 gcc 是开源免费的。这里介绍一些使用 gcc +开发单片机程序的经验。(这里不解释 gcc 是什么)。

嵌入式技术开发 1843

Handler、Looper源码流程梳理

通过Xmind将Handler流程梳理成了流程图,供大家参考,如有不足,请指点

VipPetergee的博客 283

GD32H757的can通信配置,提供方案参考!

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值。

**My Coding Family** 1836

Handler 的工作流程-源码梳理

文章目录总览创建,绑定线程特有的 Looper 实例消息发送的两种方式 sendMessage 和 post消息入队 MessageQueue#enqueueMessage()消息循环 Looper.loop()取消息 MessageQueue.next()分发处理 Handler#dispatchMessageHandler 的工作过程的时序图展示总结 总览 Handler 的工作流程 创建,绑定线程特有的 Looper 实例 发消息 Handler#sendMessage 或 Handler#post

锅ke24的专栏 628

华为OD机考双机位C卷 - AI处理器组合 (Java & Python & JS & GO & C++ & C)

> 2026华为OD机试双机位C卷 - 华为OD上机考试双机位C卷 华为OD机试双机位C卷真题目录点击查看: [【全网首发】2026华为OD机位C卷 机考真题题库含考点说明以及在线OJ(OD上机考试双机位C卷)](https://blog.csdn.net/banxia_frontend/article/details/155503868)

算法大师! 233

基于 YOLO26 的车辆实时检测与计数系统

本文提出了一种基于YOLO26的车辆实时检测与计数系统。系统采用CSPDarknet53作为主干网络,结合特征金字塔和多尺度预测实现高精度车辆检测。通过DeepSORT算法进行目标跟踪,并统计车辆数量、行驶方向和交通流量。实验表明,该系统在保持实时性能的同时,检测精度达到92.3%,可有效应用于智能交通管理。系统采用Python实现,支持GPU加速,适用于多种交通场景下的车辆监测需求。

一键难忘的博客 908

ThreadLocal源码流程梳理(Handler相关部分)

随着这篇流程梳理的完成,关于Handler相关的总体流程梳理结束

VipPetergee的博客 324

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Handler实现原理及源码解析

一,Handler的使用 1)创建全局静态常量 class Cons{ static final int MSG_WHAT_0x1000 = 0x1000; static final int MSG_WHAT_0x1001 = 0x1001; } 2)创建Handler对象 private static Handler handler = new Handler(new Handler.Callback() { @Override public bool

程序员吗? 883

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Android面试刨根问底之常用源码篇(一):Android优化,HashMap,Handler源码分析总结

本着针对面试负责任的态度,记录面试过程中各个知识点,而不是入门系列,如果有不懂的自行学习。 目前总结了以下几个方面: Android优化 HashMap分析 Handler源码分析 OkHttp分析 Retrofit分析 自定义View 由于篇幅原因拆分成两个部分分享,今天就先讲解前面三个方面,剩下的在后面继续持续更新。 Android优化 大致分为四点去回答。快、稳、小、省 1. 快 启动快,加载快,避免卡顿 基本操作 主线程不做耗时操作 application里对...

weixin_44339238的博客 391

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

小红书Android校招笔试题复盘:从Handler到启动流程的备考指南

Android校招笔试往往不只看算法刷题,更考验候选人对核心机制与工程实践的深度理解。从Java集合并发原理切入,HashMap在JDK 1.7与1.8中的差异、ConcurrentHashMap的线程安全策略,都是高频考点;而Handler消息机制与Activity启动流程则成为区分“会用”和“懂原理”的分水岭。理解Looper、MessageQueue、Binder与AMS的协作链路,并掌握APK瘦身、启动优化等工程化手段,才能真正构建起从源码到实战的完整认知。这套能力模型不仅适用于小红书等大厂校招笔试

weixin_34185320的博客 488

从源码角度简析 Android 消息机制

MessageQueue 源码解析 enqueueMessage() next() Looper 源码解析 prepare() loop() quit()、quitSafely() Handler 源码解析 构造方法 send() 系列 post() 系列 dispatchMessage() 流程一览 Handler 最佳写法 补充 MessageQueue 源码解析MessageQueue

joker 1341

Android面试题:Handler、Binder、AMS、WMS面试必问题(带答案,万字总结,精心打磨,快收藏)

前言 业内一直有一个说法:技术好的未必底层够硬,但底层扎实的学起来进步如飞。这也是为什么如今的大厂都非常注重对底层原理的考察:除了可以看出面试者的即战力,底层原理更能看出一个开发者的发展潜力。 大家对此应该也深有感受,在面试的过程中,底层原理是无论如何都躲不过去的一关。最典型的就是Framework,很多大厂在招聘中都对此做出了明确的要求: 众所众知,Android的Framework层主要是由WMS、AMS还有View所构成,这三个模块穿插交互在整个Framework中。Binder和Handler更是

Android23333的博客 1427

SpringBoot2:请求处理原理分析-接口参数解析原理(argumentResolvers)

SpringBoot

Brave_heart4pzj的博客 1434

Android面试核心原理指南:从Handler到Binder,构建完整知识体系

在Android开发领域,面试中常被问到的“八股文”并非需要机械记忆,而是理解系统运行原理的钥匙。以Handler机制为例,Looper、MessageQueue与Handler的协作构成了Android的消息驱动模型,只有深入源码才能明白为何主线程不会因死循环而卡死。同样,Binder作为Android独有的跨进程通信方案,其一次拷贝设计与线程池调度,深刻影响着系统服务的调用效率。掌握这些底层原理,不仅有助于应对面试中的连环追问,更能指导实际工程中的性能优化,例如借助Systrace分析卡顿、定位内存泄漏

weixin_29191081的博客 256

阿里Android面试全解析:从Handler到性能优化的核心技术点

在Android应用开发中,掌握底层框架与性能优化是迈向高阶工程师的必经之路。Android系统基于Linux内核,其消息驱动机制、Binder IPC、内存管理模型等构成了应用运行的基石。理解Handler、Looper、MessageQueue的工作原理,能够帮助开发者厘清异步任务与UI线程的协作关系;而JVM内存模型、垃圾回收与类加载机制,则决定了应用在资源受限环境下的稳定性与流畅度。随着移动互联网对用户体验要求不断提高,启动优化、内存优化、卡顿治理等工程实践成为大厂面试的高频考点。本文结合阿里巴巴A

weixin_29192365的博客 342

网易Android校招笔试题解析:从Handler到Binder的核心考点

在Android开发中,进程通信与消息机制是构建稳定应用的基础。Binder作为Android系统核心的IPC机制,通过一次内存拷贝实现高效的跨进程通信;而Handler消息循环则负责主线程与子线程之间的协作,是异步任务和UI更新的基石。深入理解这些底层原理,不仅是技术进阶的必经之路,也是应对大厂校招笔试的关键。无论是Activity启动流程、自定义View绘制,还是性能优化与内存管理,这些知识点都在笔试中反复出现。本文以网易Android校招笔试题为线索,系统梳理了Activity组件、Binder通信、

weixin_29175469的博客 255
上一篇: 算法 中的 散列表(哈希表)
下一篇: 一个线程中有几个Handler?几个Looper?怎么保证?
Seas.Su
博客等级 码龄9年 19粉丝 67原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值