你真的理解Android Handler吗

本文详细解析了Android中Handler的工作原理,包括消息的创建、发送、接收及处理过程,阐述了Handler、Looper、MessageQueue和Message之间的关系,以及它们在主线程中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 讲解原理前先看看Handler一般是如何在activity中使用的,如下为简单的例子
private MyHandler myHandler = new MyHandler();

 1.1重写Handler中的handleMessage方法

private class MyHandler extends Handler{

        @Override

        public void handleMessage(Message msg) {

            Toast.makeText(getApplicationContext(),

                    "[handlerCount]"+(handlerCount++)+"[what]"+msg.what,                                                                         Toast.LENGTH_SHORT).show();

        }

    }

1.2在按键点击事件中添加如下代码,即可将what==1的msg发送到MyHandler 中的handleMessage方法中

Message msg = new Message();
msg.setTarget(myHandler);
msg.what =1;
msg.sendToTarget();

或从Message池中获取msg并发送

myHandler.obtainMessage(1).sendToTarget();
  1. Handler的处理模型是消息驱动,那么也意味着至少包含如下3个组件:循环组件(Looper)、消息(Message)、消息处理组件(Handler->handleMessage),如下给出大致的模型图

      

MessageQueue组件则对消息(Message)进行了统一的存放并管理,即消息队列

2.1由图可以看出大致步骤如下:

  1. Handler不断的将消息(Message)放入消息队列(MessageQueue)中
  2. 循环组件(Looper)不断的从消息队列(MessageQueue)中取出消息(Message)并分发至具体的处理组件(Handler->handleMessage)

2.2从如上步骤中能得出以下问题

  1. 消息是从何而来的?
  2. 对于消息的处理是如何循环起来的,即Looper组件从何而来?
  3. Handler、MessageQueue、Message、Looper之间又是如何建立关系的?
  4. Looper中又是如何处理MessageQueue中的Message的?

接下来则一一进行解答。

2.3   消息是从何而来的

2.3.1重新实例化一条消息

Message msg = new Message();
msg.setTarget(myHandler);
msg.what =1;
msg.sendToTarget();

2.3.2从Message池中获取Message并发送,如此能提高效率

myHandler.obtainMessage(1).sendToTarget();

2.4 对于消息的处理是如何循环起来的,即Looper组件从何而来

一般情况下,一款应用即代表linux下的一例进程,而包含UI的Activity则运行于该进程下的主线程中。下面看看Activity的onCreate方法是如何被调用的。

在onCreate中添加线程栈打印方法,代码如下

运行后得到如下线程调用栈 

从线程栈可以清楚的看到主线程由ZygoteInit启动,经过一系列调用后可以看到我们自己编写的Activity onCreate方法则被ActivityThread的main调用,如下列出重要函数

public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
...
Looper.loop();
}

 Looper的实例化则位于Looper.prepareMainLooper();静态方法中,如下为方法调用关系 

 

 

由uml图可知,在执行完Looper的prepareMainLooper()静态方法后主线程的循环组件也已实例化,且在Looper的构造方法中实例并关联了消息队列(MessageQueue)的,由此也可以得出如下结论:

  1. 主线程与Looper是一一对应的,即一个线程中只有一个循环组件(Looper)
  2. Looper与消息队列(MessageQueue)也是一一对应的,即一个循环组件(Looper)只有一个消息队列(MessageQueue)

其中主线程的Looper被sMainLooper指向,并可通过myLooper()方法进行获取。

2.5   Handler、MessageQueue、Message、Looper之间又是如何建立关系的

2.5.1Handler在实例化Message时指定并关联,代码如下

Message msg = new Message();
msg.setTarget(myHandler);
msg.what =1;

2.5.2 Message与MessageQueue之间的关系建立,实际上仅仅是通过Handler将Message放入Looper中的MessageQueue中的,代码表现为消息(Message)调用sendToTarget方法将自己压入指定Looper的MessageQueue中,代码流程大致如下 

 

其中C1使用的mQueue则是在Looper实例化时指定。

2.5.3 MessageQueue与Looper之间的关系建立,见问题二分析

2.6.   Looper中又是如何处理MessageQueue中的Message的 

在ActivityThread的main方法中,最终调用Looper.loop()进行message的处理,时序图如下

从时序图中可以看到,loop方法最终将调用Handler中的dispatchMessage来对消息(Message)进行分发

已分析到此,对于消息的具体处理不再进行分析,并向阅读者提出如下两个问题,希望能认真的思考下

2.6.1 对Message的处理,除了重写Handler中的handleMessage方法,还能通过哪些方式?

2.6.2 对Message中消息处理方法的调用优先级又是怎样的? 

2.6.3 为何在四大组件中通过Handler()既可以在handleMessage方法对UI控件进行操作?

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值