Handler消息机制源码分析

本文深入解析Android中Handler机制的工作原理,包括Looper.prepare()与Looper.loop()的作用,消息发送流程,以及如何在子线程中正确使用Handler。

    public static final Looper myLooper() {
        return (Looper)sThreadLocal.get();
    }

先来个Handler执行过程的总结:


    1、 Looper.prepare()方法
        为当前线程绑定looper,
        在looper构造方法中创建一个messageQueue

    2、 创建handler 重并写handleMessage方法

    3、 使用handler发送消息,最终消息都会发送至messageQueue对象中,在messageQueue当中,所有的message按应该执行的时间的先后顺序,从小到大排列

    4、Looper.loop()
        在此方法中,开启死循环,不断的从messageQueue中取出应该执行的message,并执行message 对应的handler中的dispatchMessage方法,即,执行我们重写的handleMessage方法

参照以上分析在子线程中创建Handler对象:

	new Thread(){
	    @Override
	    public void run() {
		Message msg = Message.obtain();
		Looper.prepare();//若没有调用此方法则抛出异常 Can't create handler inside thread that has not called Looper.prepare()
		Handler handler2 = new Handler(){
		    public void handleMessage(Message msg) {
			Toast.makeText(MainActivity.this, "收到子线程message消息", 0).show();
		    };
		};
		handler2.sendMessage(msg);
		Looper.loop();
	    }
	}.start();
对比在主线程中创建Handler实例对象我们发现,在子线程中创建Handler对象需要在创建前调用Looper.prepare()方法在创建后调用Looper.loop方法,那究竟这两个方法是做什么的呢?

先看看系统的Looper.prepare方法:

public static final void prepare() {

        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
		// 为当前线程绑定一个looper对象,以sThreadLocal为key
        sThreadLocal.set(new Looper());
    }
即:调用Looper.prepare方法时为当前线程绑定了一个Looper对象,所以Looper.prepare方法只能调用一次,即一个线程只能有一个Looper对象

再看看Looper的构造方法:

 private Looper() {
        mQueue = new MessageQueue();
    }
因为一个线程只能有一个Looper对象,所以一个线程也只能有一个MessageQueue对象


先让我们看看Handler的构造方法:

public Handler() {
	//获得当前线程的looper对象
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
		// 获得looper中MessageQueue的引用
        mQueue = mLooper.mQueue;
    }

再看看系统的Looper.myLooper方法:即获取调用Looper.prepare方法时保存在sThreadLoad的Looper对象,所以Looper.prepare方法要在new Handler方法前调用

    public static final Looper myLooper() {
        return (Looper)sThreadLocal.get();
    }

即:当创建Handler时会先调用Looper.myLooper()方法获取当前线程的Looper对象,如果Looper==null,则抛出异常

通过以上两个方法,当前线程的唯一Looper对象和MessageQueue对象都已创建,接下来该sendMessage了

查看系统源码可知:sendEmptyMessage等,发送信息的方法,最终都是调用了SendMessageAtTime(msg,when);

而SendMessageAtTime(msg,when);方法最终的目的就是为了queue.enqueueMessage(msg, uptimeMillis);,其中msg为发送的Message对象,uptimeMillis为SystemClock.uptimeMillis() + when

查看系统的enqueueMessage方法,该方法最终实现在messageQueue当中,所有的message按执行的先后顺序,从小到大排列

final boolean enqueueMessage(Message msg, long when) {
       
            msg.when = when; // 将执行时间设置给msg.when
            Message p = mMessages;  // 定义变量p = mMessage  ,mMessage初终指向对列的第一个Message 对象

            if (p == null || when == 0 || when < p.when) {
				// 当队列中为空的时候,mMessage = msg
                msg.next = p;
                mMessages = msg;
                this.notify();
            } else {
				// 否则将要进入队列的msg的执行时间和队列中的message的执行时间进行比较,
				// 最终会使messageQueue中的所有的message按时间为顺序从小到大排列
				// 即按执行的先后顺序排列
                Message prev = null;
                while (p != null && p.when <= when) {
                    prev = p;
                    p = p.next;
                }
                msg.next = prev.next;
                prev.next = msg;
                this.notify();
            }
        }

消息发送成功这时候该调用Looper.loop方法:即完成了从MessageQueue中取出需要执行的Message,并执行我们重写的handlMessage方法

 public static final void loop() {
	//获得当前线程的looper对象及messageQueue对象
        Looper me = myLooper();
        MessageQueue queue = me.mQueue;

	//开启while(true)循环
        while (true) {
	    //从消息队列中取出一个message,如果message执行时间不到,那就wait等一会
            Message msg = queue.next(); // might block

	    //执行message 对应的handler中的dispatchMessage方法,即,执行我们重写的handleMessage方法
             msg.target.dispatchMessage(msg);

            }
        }
    }





















内容概要:本文系统整理了《微软面试100题完整版(含解析+备考指南)2026最新求职资源》,涵盖算法编程、逻辑思维、计算机基础、系统设计与工程实践、职场综合五大核心题型,共100道高频原题,均来自微软近十年真实面试题库,剔除过时内容,新增AI工程应用、轻量化系统设计等2026年前沿考点。每道题目配有详细解题思路与考察要点,覆盖数据结构、动态规划、位运算、网络协议、数据库事务、微服务架构、高并发设计等关键技术领域,并包含逻辑推理、工程排查、产品权衡等综合素质题目,全面适配微软海内外各岗位面试需求。此外,文章还提供分层刷题策略、地域差异化备考建议及完整资源获取路径,助力求职者高效通关初面、复面与终面。; 适合人群:准备应聘微软的应届毕业生、1-5年工作经验的技术岗从业者(如软件开发、算法、测试、数据、运维等),以及计划投递微软海外岗位的求职者;尤其适合缺乏系统面试准备、希望提升解题思维与工程表达能力的人群。; 使用场景及目标:①针对微软技术面试中的算法题进行专项突破,掌握最优解法与代码规范;②训练逻辑思维与系统设计能力,应对高阶岗位考察;③准备终面综合问题,提升职场素养与岗位匹配度表达;④根据国内/海外不同考点调整复习重点,实现精准备考。; 阅读建议:此资源以真题为核心,强调解题思路而非死记硬背,建议按“分类刷题—总结模板—模拟手撕—复盘优化”流程学习,重点关注代码边界处理、复杂度优化与中英文表达逻辑,结合自身背景补充项目复盘与系统设计练习,全面提升面试实战能力。
内容概要:本文围绕永磁同步电机(PMSM)的二阶线性自抗扰矢量控制系统展开深入研究,重点实现了基于Simulink的系统建模仿真。研究采用二阶线性自抗扰控制(LADRC)策略,结合扩张状态观测器(ESO)对系统内部动态和外部扰动进行实时估计与前馈补偿,有效提升了电机在负载突变、参数摄动等复杂工况下的转速控制精度、动态响应速度与系统鲁棒性。文中详细构建了电流环与转速环的双闭环矢量控制架构,系统分析了控制器关键参数的设计方法、观测器带宽的整定原则以及整体系统的稳定性条件,并通过大量仿真实验验证了所提出控制方案相较于传统PI控制在抗干扰能力、响应性能和鲁棒性方面的显著优越性。; 适合人群:具备自动控制理论、电机控制原理、现代控制理论等相关专业知识,熟悉Simulink/Matlab仿真环境,且有一定工程实践经验的电气工程、自动化、控制科学与工程等领域的硕士/博士研究生、科研人员及从事高性能电机驱动系统开发的工程技术人员。; 使用场景及目标:①为高等院校和科研机构提供先进电机控制算法的教学案例与科研实验平台,深化对自抗扰控制(ADRC)理论的理解;②为企业在高性能伺服驱动、新能源汽车电驱系统、工业自动化等领域的下一代控制器研发提供可靠的技术参考、仿真验证方案和原型设计基础;③帮助研究人员系统掌握ADRC的核心思想、设计流程及其在高精度运动控制系统中的具体工程实现方法。; 阅读建议:学习者应具备扎实的自动控制与电机学理论基础及Simulink建模能力,建议结合韩京清教授的经典ADRC文献进行原理性学习,深入理解ESO的观测机理与TD的安排机制。在仿真实践中,应动手调试控制器带宽、观测器增益等核心参数,对比分析不同扰动工况(如突加负载、转速指令跳变)下的系统响应曲线,以直观感受控制性能的差异。为进一步深化研究,可将该仿真模型与硬件在环(HIL)测试平台或实际电机实验平台对接,完成从算法设计、仿真验证到物理实现的完整闭环验证流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值