发布时间:2026/8/14 2:20:18
android Handler , Looper , Message , MessageQueue 详解 一、基础Q1请简述 Handler 机制的工作原理核心回答Handler 发送消息 → MessageQueue 按时间排序存储 → Looper 无限循环取出 → 回调 Handler 处理。细节MessageQueue不是队列是单向链表按when触发时间戳排序Looper.loop()中queue.next()无消息时通过native epoll阻塞不消耗 CPU最终msg.target.dispatchMessage(msg)target就是发送该消息的 HandlerQ2一个线程可以有几个 Handler几个 Looper数量原因Looper1 个ThreadLocal存储prepare()时检查重复重复会抛异常Handler多个多个 Handler 可以共享同一个 Looper 和 MessageQueue源码验证java// Looper.prepare() if (sThreadLocal.get() ! null) { throw new RuntimeException(Only one Looper may be created per thread); }Q3为什么主线程的 Looper.loop() 死循环不会导致 ANR核心要点ANR 的本质是消息处理超时不是死循环本身。深入解析loop()中的queue.next()无消息时会通过native 层的epoll_wait阻塞线程释放 CPU有消息来时native 层被唤醒继续执行ANR 发生在dispatchMessage()里处理消息耗时过长如 5s 内未响应输入所以死循环 阻塞 事件驱动模型这是高性能的Q4MessageQueue 的数据结构是什么答案单向链表按when时间戳排序java// Message.java Message next; // 链表指针 long when; // 触发时间为什么不用数组/堆不需要随机访问只取头部 → 链表 O(1)插入按时间排序数量通常不多O(n) 可接受内存更紧凑且支持对象池复用二、进阶深挖Q5Handler 的sendMessageDelayed()是怎么实现延迟的核心原理不是真的延迟发送而是提前发送按时间排队。流程计算when SystemClock.uptimeMillis() delayMillisenqueueMessage()按when插入链表合适位置Looper循环到该消息时检查when是否到达未到计算剩余时间通过nativenativePollOnce(ptr, timeout)阻塞等待已到取出处理Q6Handler 内存泄漏的原因如何解决原因非静态内部类Handler持有外部Activity的引用延迟消息如postDelayed在 Activity 销毁时仍在 MessageQueue 中Message 持有 HandlerHandler→Activity导致 Activity 无法被回收解决方案3种java// 方案1静态内部类 WeakReference private static class SafeHandler extends Handler { private WeakReferenceActivity ref; SafeHandler(Activity activity) { ref new WeakReference(activity); } Override public void handleMessage(Message msg) { Activity activity ref.get(); if (activity ! null !activity.isFinishing()) { // 处理消息 } } } // 方案2Activity.onDestroy() 时移除消息 Override protected void onDestroy() { super.onDestroy(); handler.removeCallbacksAndMessages(null); } // 方案3使用 Lifecycle 组件自动管理Q7Message.obtain() 和 new Message() 有什么区别答案obtain()从消息对象池中复用new会创建新对象。源码javapublic static Message obtain() { synchronized (sPoolSync) { if (sPool ! null) { Message m sPool; sPool m.next; m.next null; m.flags 0; sPoolSize--; return m; } } return new Message(); // 池空时才 new }好处避免频繁 GC提升性能。Android 系统大量消息传递场景如触摸事件、绘制都用这个池。Q8post(Runnable)和sendMessage(Message)有什么区别post(Runnable)sendMessage(Message)本质把 Runnable 赋值给msg.callback直接发送 Message处理优先级高dispatchMessage先检查 callback低使用场景简单任务需要携带复杂数据源码javapublic final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } private static Message getPostMessage(Runnable r) { Message m Message.obtain(); m.callback r; // Runnable 被包装进 callback return m; }Q9IdleHandler 是什么使用场景定义当 MessageQueue 空闲无消息或消息未到触发时间时执行的回调。使用javaLooper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() { Override public boolean queueIdle() { // 执行低优先级任务 return false; // true保留false执行完移除 } });经典场景启动优化主线程空闲时加载非关键资源延迟初始化如LeakCanary的初始化UI 收尾如RecyclerView预加载Q10什么是同步屏障Sync Barrier原理插入一个target null的特殊 Message拦截其后所有同步消息只允许异步消息通过。使用场景ViewRootImpl在scheduleTraversals()时插入屏障确保Choreographer的 VSync 异步消息优先执行避免掉帧注意同步屏障是hide API应用层不能直接调用。三、实战场景题Q11如何在子线程中创建 Handlerjavanew Thread(() - { // 子线程默认没有 Looper必须手动创建 Looper.prepare(); Handler handler new Handler(Looper.myLooper()) { Override public void handleMessage(Message msg) { // 在子线程处理 } }; Looper.loop(); // 阻塞开始消息循环 // 退出时子线程可以退出 // Looper.myLooper().quitSafely(); }).start();更推荐使用HandlerThreadjavaHandlerThread thread new HandlerThread(bg); thread.start(); Handler handler new Handler(thread.getLooper());Q12Looper.quit()和quitSafely()的区别quit()quitSafely()行为立即退出清空 MessageQueue设置退出标记处理完已有消息后退出延迟消息直接丢弃丢弃只保证当前已到达的消息使用子线程 Looper子线程 Looper主线程 Looper 不允许 quit会抛异常。Q13主线程的 Looper 是什么时候创建的答案ActivityThread.main()中。java// ActivityThread.java public static void main(String[] args) { Looper.prepareMainLooper(); // 创建主线程 Looper ActivityThread thread new ActivityThread(); thread.attach(false); Looper.loop(); // 开始循环永不退出 }Q14为什么 Handler 构造方法里要求 Looper 不能为 nulljavapublic Handler(Looper looper) { this(looper, null, false); }原因Handler 必须关联一个 MessageQueue 才能发消息MessageQueue 来自 Looper如果当前线程没有调用Looper.prepare()Looper.myLooper()返回 null直接抛异常避免 NPE 或消息丢失Q15触摸事件是怎么通过 Handler 机制传递到 View 的流程InputDispatchernative收到触摸事件通过JNI将事件封装成Message发送到主线程的MessageQueueLooper取出消息ViewRootImpl的WindowInputEventReceiver处理最终分发到DecorView→ViewGroup→View的dispatchTouchEvent()这解释了为什么在主线程执行耗时操作会导致触摸无响应——消息被堵在队列里。四、面试速记口诀问题一句话答案Handler 发消息去哪MessageQueue链表Looper 干嘛的死循环取消息交给 Handler为什么不会卡死native epoll 阻塞有消息才唤醒延迟消息怎么实现提前入队按时间排序到点才处理内存泄漏怎么解静态内部类 WeakReference removeCallbacks子线程用 Handler先Looper.prepare()Looper.loop()

相关新闻

2026/8/14 2:15:18

双连通分量例题

[CEOI2017] One-Way Streets 题意:给定一个无向连通图,以及若干对点 (x, y),要求给每条边定向,使得 x 能到达 y,求哪些边的方向是唯一确定的,并输出其方向。 环上的边方向不唯一 如果一条无向边 (u, v) 位于…

2026/8/14 2:15:18

Java应用测试指南:单元测试与集成测试的全面解析与实践

1. 引言:为什么我们需要测试?在软件开发过程中,代码质量直接关系到产品的稳定性、可维护性和交付效率。想象一下,你开发了一个用户注册功能,上线后才发现密码验证逻辑有漏洞——这可能导致用户账户被盗。测试就是我们的…

2026/8/14 4:50:27

OpenClaw架构实战:构建高度解耦的跨平台智能对话机器人

1. 项目概述:从“紧耦合”的泥潭到“解耦”的优雅最近在折腾一个智能对话机器人项目,想把服务能力从单一的Web界面扩展到像Telegram、飞书、钉钉这些日常高频使用的IM工具里。一开始,我图省事,直接把消息接收、逻辑处理和模型调用…

2026/8/14 4:50:27

Spark实战:电商用户行为分析全流程,从数据探索到转化漏斗

上周在帮一个做电商的朋友排查数据问题,他手头有一堆用户行为日志,想看看用户到底在怎么逛他的店,但用传统数据库跑起来慢得让人心焦。他问我:“有没有什么办法,能把这些点击、浏览、加购、下单的数据快速跑出点门道来…

2026/8/14 4:50:27

CUDA生态核心组件解析:cuBLAS、cuDNN、NCCL、Triton与CUTLASS实战指南

1. 项目概述:大模型时代的“基建狂魔”——CUDA生态如果你正在或准备踏入大模型、深度学习这个领域,那么“CUDA”这个词对你来说,绝对不是一个陌生的概念。它就像是这个领域的“水电煤”,是支撑起所有上层应用的基础设施。但CUDA本…

2026/8/14 4:45:26

java知识点自理1

一、开发环境与程序结构 JDK / JRE / JVM 关系:JDK ⊃ JRE ⊃ JVM(JDK JRE 开发工具,JRE JVM 核心类库)。 环境变量:需配置 JAVA_HOME(指向JDK安装目录)并添加到 Path(%JAVA_HOM…

2026/8/14 4:27:24

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/14 4:27:24

当 LLM 遇见大文档:主流开源项目如何处理上下文超限

从 Agentic Loop 到 Repo Map,七种策略与六类陷阱引言:128K vs 10MB 的硬冲突 2026 年的 LLM 上下文窗口已达到 128K ~ 1M token(≈ 0.5MB ~ 4MB 文本),但 LLM 想要处理的真实数据规模远远超过这个量级:真实…

2026/8/14 0:00:09

Flutter与OpenHarmony实现剧本杀组队表单开发实战

1. 项目概述在移动应用开发领域,跨平台框架Flutter因其高效的开发体验和出色的性能表现,已经成为众多开发者的首选。而OpenHarmony作为新兴的操作系统平台,其开放性和灵活性为开发者提供了全新的可能性。本文将聚焦于一个实际应用场景——剧本…

2026/8/14 0:00:09

VSCode高效Git管理:从入门到实战技巧

1. 为什么选择VSCode进行Git代码管理作为微软推出的轻量级代码编辑器,Visual Studio Code(简称VSCode)已经成为全球开发者使用率最高的编辑器之一。根据2023年Stack Overflow开发者调查,VSCode的市场占有率高达74.48%。它内置的Gi…

2026/8/14 4:27:24

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/14 4:27:24

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/14 4:27:24

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…