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

试从源码角度分析Handler的post和sendMessage方法的区别和应用场景?

更多面试题请看这里:https://interview.raoyunsoft.com/

核心区别分析

通过源码分析,post()sendMessage()的本质区别在于消息处理路径不同:

// 源码核心路径(简化版)
public final boolean post(Runnable r) {return sendMessageDelayed(getPostMessage(r), 0);
}private static Message getPostMessage(Runnable r) {Message m = Message.obtain();m.callback = r;  // 关键:将Runnable赋值给callbackreturn m;
}public void dispatchMessage(Message msg) {if (msg.callback != null) {handleCallback(msg);  // post消息走此分支} else {if (mCallback != null) {if (mCallback.handleMessage(msg)) return;}handleMessage(msg);  // sendMessage消息走此分支}
}
处理流程对比
方法消息封装方式处理入口是否需要重写方法
handler.post()通过getPostMessage()封装消息
(设置msg.callback=Runnable
handleCallback()
msg.callback.run()
不需要重写handleMessage()
handler.sendMessage()直接创建Message对象先检查mCallback.handleMessage()
再调用handleMessage()
需重写handleMessage()或设置Callback
关键源码解析
  1. post()的消息处理路径

    private static void handleCallback(Message message) {message.callback.run(); // 直接执行Runnable的run()
    }
    
    • 消息由post()提交时,自动触发Runnable.run()
    • 适用于无需消息内容的简单任务
  2. sendMessage()的处理优先级

    public void dispatchMessage(Message msg) {if (msg.callback == null) {if (mCallback != null) {if (mCallback.handleMessage(msg)) return; // 优先处理Callback}handleMessage(msg); // 最终调用重写的方法}
    }
    
    • 支持两种处理方式:
      • 通过Handler.Callback接口处理(可拦截消息)
      • 通过重写handleMessage()处理
应用场景对比
场景推荐方法示例优势
更新UI控件状态post()handler.post(() -> textView.setText("Done"))代码简洁,无需消息对象
携带复杂数据的跨线程通信sendMessage()Message msg = handler.obtainMessage();
msg.obj = dataModel;
handler.sendMessage(msg);
支持结构化数据传输
需要统一处理消息的业务逻辑sendMessage() + Callbacknew Handler(new Handler.Callback() {
 @Override public boolean handleMessage(Message m) {
  // 集中处理所有消息
 }
})
避免继承Handler类
延迟执行简单任务postDelayed()handler.postDelayed(task, 1000)内置时间控制能力
实战建议
  1. 优先用post()的场景

    • 执行View.post()保证线程安全更新UI
    • 短耗时任务(如切换按钮状态)
    // 经典用法:在子线程更新UI
    new Thread(() -> {// ...耗时操作handler.post(() -> progressBar.setVisibility(View.GONE));
    }).start();
    
  2. 优先用sendMessage()的场景

    • 需要传递多个数据字段(用Bundle
    • 需要消息优先级控制(sendMessageAtFrontOfQueue()
    • 需要复用消息处理逻辑(通过Callback统一处理)
    // 携带复杂数据
    Message msg = handler.obtainMessage(MSG_TYPE_FILE);
    Bundle bundle = new Bundle();
    bundle.putSerializable("file", fileData);
    msg.setData(bundle);
    handler.sendMessage(msg);
    
  3. 避免内存泄漏
    两种方法都需注意:

    // 正确做法:使用静态内部类+弱引用
    static class SafeHandler extends Handler {private final WeakReference<Activity> mActivity;SafeHandler(Activity activity) {mActivity = new WeakReference<>(activity);}@Overridepublic void handleMessage(Message msg) {Activity activity = mActivity.get();if (activity != null) {// 安全处理消息}}
    }
    

关键结论:两种方法最终都通过sendMessageAtTime()发送消息,但post()为消息添加了callback标记,使得dispatchMessage()直接执行Runnable.run(),而sendMessage()需依赖handleMessage()Callback处理。根据是否需要携带数据和代码复用需求选择合适方式。

http://www.dtcms.com/a/477601.html

相关文章:

  • 网站流量如何突破厦门建设局局长李德才
  • 外包网站设计网站建设的主要技术路线
  • iOS 26 电耗监测与优化,耗电问题实战 + 多工具 辅助策略
  • 企业前端网站模板下载 HTML前端模板网站
  • 【RabbitMQ】 RabbitMQ Overview
  • uniapp+vue3+vite+ts+xr-frame实现ar+vr渲染踩坑记
  • 如何选择适合的加密方法来保护云计算中的数据
  • Linux 云计算核心技术:原理、组件与 K8s 实战部署
  • aws docker安装,ec2安装docker-compose
  • 2025上海国际数据中心及云计算产业展览会影响力如何?有啥亮点?
  • 关于网站建设的意义亚马逊计划裁员1万人
  • 南宁做网站培训网页游戏排行榜前十2023
  • Windows ACL 原理详解与使用示例
  • Rider下Avalonia 项目启动问题完整解决方案
  • MySQL默认端口为何是3306?修改后如何管理?
  • 中间件常用组件的原理和设计
  • Java EE初阶启程记13---JUC(java.util.concurrent) 的常见类
  • 25.负载均衡-Nginx、HAProxy、LVS 全解析
  • ubantu的adb命令(首次安装adb)
  • 辽宁平台网站建设哪里好电商网站怎样优化
  • 万商惠网站建设系统开发人才网站建设经费用途
  • 欧普建站做网站需要apache
  • 天津做网站企业天津定制网站建设商店设计
  • 天猫网站设计大连市那里做网站宣传的好
  • Linux curl 与 wget 区别
  • Centos7详细安装过程
  • SpringBoot 集成 LangChain4j RAG PostgreSQL 搜索
  • 扫地机器人算法分析
  • C语言——深入解析C语言指针:从基础到实践从入门到精通(二)
  • JSAR 空间小程序开发全指南:从环境搭建到跨场景应用落地