千家信息网

解析Android中Handler机制原理

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,Handler是Android中提供的一种异步回调机制,也可以理解为线程间的消息机制。为了避免ANR,我们通常会把一些耗时操作(比如:网络请求、I/O操作、复杂计算等)放到子线程中去执行,而当子线程需
千家信息网最后更新 2026年11月02日解析Android中Handler机制原理

Handler是Android中提供的一种异步回调机制,也可以理解为线程间的消息机制。为了避免ANR,我们通常会把一些耗时操作(比如:网络请求、I/O操作、复杂计算等)放到子线程中去执行,而当子线程需要修改UI时则子线程需要通知主线程去完成修改UI的操作,则此时就需要我们使用Handler机制来完成子线程与主线程之间的通信。

1. Handler的一般使用步骤

在明确了Android中只有主线程能修改UI界面、子线程执行耗时操作的前提后,下面一起来学习下Handler的使用步骤。

  1. 在主线程中创建Handler实例,并且重写handlerMessage方法。

    private Handler handler = new Handler(){@Overridepublic void handleMessage(Message msg) {    switch (msg.what) {        case 1:            //执行相关修改UI的操作            break;        }    }};
  2. 子线程中获取Handler对象,在需要执行更新UI操作的地方使用handler发送消息

    Message msg = Message.obtain();msg.obj = "content";msg.what = 1;//发送消息给Handlerhandler.sendMessage(msg);   
  3. 在handlerMessage方法中的Switch里面,根据case下不同的常量执行相关操作

以上只是Handler的一种使用方式,由于本文的重点是探究Handlerde原理,故其他使用方式这里不重点介绍。

2. 重要类的职责

在深入了解Handler机制原理之前,我们应该明确在Handler机制中几个重要类的职责。

  • Handler:负责发送处理消息
  • MessageQueue:消息队列,负责存储消息
  • Message: 具体发送的消息
  • Looper: 负责循环取出消息给Handler处理
  • ThreadLocal: 用于线程间的数据隔离,在每个线程中存放各自对应的Looper
3. Handler机制原理
  • 每个Handler都会关联一个消息队列,消息队列又是封装在Looper对象中,而每个Looper又会关联一个线程。这样Handler、消息队列、线程三者就关联上了。

  • Handler是一个消息处理器,将消息发送给消息队列,然后再由对应的线程从消息队列中逐个取出,并执行。

  • 默认情况下,消息队列只有一个,也就是主线程的消息队列,该消息队列通过Looper.prepareMainLooper()方法创建,最后执行Looper.loop()来循环启动消息。

以上叙述可能有点空洞,下面我们结合源码一起来理解:

3.1 Handler是如何关联消息队列和线程的?

我们首先看Handler默认的构造函数:

     public Handler(Callback callback, boolean async) {    //代码省略    mLooper = Looper.myLooper();//获取Looper    if (mLooper == null) {        throw new RuntimeException(            "Can't create handler inside thread that has not called Looper.prepare()");    }        mQueue = mLooper.mQueue;//通过Looper对象获取消息队列        mCallback = callback;        mAsynchronous = async;    }    //获取Looper对象    public final Looper getLooper() {        return mLooper;     }

从Handler的构造函数中我们可以发现,Handler在初始化的同时会通过Looper.getLooper()获取一个Looper对象,并与Looper进行关联,然后通过Looper对象获取消息队列。那我们继续深入到Looper源码中去看Looper.getLooper()是如何实现的。

    //初始化当前线程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();        }     }    //为当前线程设置一个Looper    private static void prepare(boolean quitAllowed) {    if (sThreadLocal.get() != null) {        throw new RuntimeException("Only one Looper may be created per thread");    }         sThreadLocal.set(new Looper(quitAllowed));     }

从上面的程序可以看出通过prepareMainLooper(),然后调用 prepare(boolean quitAllowed)方法创建了一个Looper对象,并通过sThreadLocal.set(new Looper(quitAllowed))方法将该对象设置给了sThreadLocal。

    //通过ThreadLocal获取Looper    public static @Nullable Looper myLooper() {        return sThreadLocal.get();     }

通过Looper中的预备工作,sThreadLocal中已经存储了一个Looper对象,然后myLooper()方法通过sThreadLocal.get()方法获取到了Looper。那么消息队列就与线程关联上了,所以各个线程只能访问自己的消息队列。

综上所述,我们可以发现消息队列通过Looper与线程关联上了,而Looper又与Handler是关联的,所以Handler就跟线程、线程的消息队列关联上了。

3.2 如何执行消息循环?

在创建Looper对象后,通过Handler发来的消息放在消息队列中后是如何被处理的呢?这就涉及到了消息循环,消息循环是通过Looper.loop()方法来建立的。源代码如下:

    //执行消息循环    public static void loop() {    final Looper me = myLooper();    if (me == null) {        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");    }    final MessageQueue queue = me.mQueue;//获取消息队列    //代码省略    for (;;) {//死循环        Message msg = queue.next(); // 获取消息        if (msg == null) {            // No message indicates that the message queue is quitting.            return;        }        //代码省略        try {            msg.target.dispatchMessage(msg);//分发消息        } finally {            if (traceTag != 0) {                Trace.traceEnd(traceTag);            }        }        //代码省略        msg.recycleUnchecked();//消息回收         }    }   

从源码中我们可以看出,loop()方法实质上就是通过一个死循环不断的从消息队列中获取消息,然后又不断的处理消息的过程。

3.3 消息处理机制
msg.target.dispatchMessage(msg);//分发消息

我们从loop中的 dispatchMessage()方法入手,看看谁是该方法的调用者,深入Message源码中看看target的具体类型:

    public final class Message implements Parcelable {        //代码省略        /*package*/ int flags;        /*package*/ long when;        /*package*/ Bundle data;        /*package*/ Handler target;        /*package*/ Runnable callback;        /*package*/ Message next;        //代码省略    }

从源码中我们可以看到其实target就是Handler类型。所以Handler是将消息发送到消息队列暂时存储下,然后又将消息发送给Handler自身去处理。那我们继续到Handler源码中去看看Handler是如何处理消息的:

public void dispatchMessage(Message msg) {    if (msg.callback != null) {        handleCallback(msg);    } else {        if (mCallback != null) {            if (mCallback.handleMessage(msg)) {                return;            }        }        handleMessage(msg);    }}


private static void handleCallback(Message message) {    message.callback.run();}


/** * Subclasses must implement this to receive messages. * 消息处理方法为一个空方法,由子类去实现 */public void handleMessage(Message msg) {}

从上面的源码中可以看出,dispatchMessage(Message msg)只负责分发Message。从Message源码中我么可以知道callback为Runnable类型,如果callback不为空,则执行 handleCallback方法来处理,而该方法又会调用callback.run();如果如果callback为空,则调用handleMessage来处理消息,而该方法又为空,所以我们会在子类中重写该方法,并将修改UI的代码写在里面。之所以会出现这两种情况,是因为Handler发送消息有两种形式:

  • 在本文的一般使用步骤中,我使用的是sendMessage(msg)发送消息,此时callback就为空。
  • 当使用post发送消息时,callback就不为空。

以上就是Handler机制的原理,大致可以总结为:在子线程中Handler将消息发送到MessageQueue中,然后Looper不断的从MessageQueue中读取消息,并调用Handler的dispatchMessage发送消息,最后再Handler来处理消息。为了更好的帮助大家一起理解,我画了一个Handler机制的原理图:

关于Handler机制补充如下几点:

  • Handler创建消息时用到了消息池,在创建消息时会先从消息池中去查询是否有消息对象,如果有,则直接使用消息池中的对象,如果没有,则创建一个新的消息对象。
  • 使用ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。之后其他Handler初始化的时候直接获取第一个Handler创建的Looper
消息 线程 队列 方法 对象 处理 机制 关联 源码 循环 代码 原理 不断 就是 步骤 类型 存储 重要 函数 只有 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技公司经营范围 科技赋能下的互联网金融 金融科技创新监管互联网金融 没上市的科技互联网公司 善班互联网科技 互联网科技股票 睿民互联网科技 友谊互联网络科技 科技赋能互联网健康 996高科技互联网公司 内蒙古九一互联网科技 互联网科技公司营业执照怎么办理 深圳互联网科技的发展 郑州欣桑互联网科技有限公司 上海同邻互联网科技有限公司规模 广州梦谷互联网科技有限公司领导 版纳互联网科技选哪家 科技互联网经济论坛 河南商务圈互联网科技有限公司 重庆科技产业互联网有哪些 科技企业和互联网企业 齐家互联网科技有限公司 互联网教育科技公司vipkid 荆州市昕露互联网络科技有限公司 和信科技工业互联网 恒生互联网科技指数跳水 高科技互联网发展前景如何 启辰互联网科技 互联网科技收购价值 知域互联网科技有限公司官网
0