Handler在android程序开发中使用的非常频繁、我们知道android是不允许在子线程中更新UI的,这就需要借助Handler来实现,那么你是否想过为什么一定要这个这样子做呢?而且Handler的内部消息处理机制究竟是什么样的呢?Handler的原理是需要通过源代码才能说的清楚的,而且它处理机制比较复杂。
Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分在消息队列中逐一将消息取出,然后对消息进行处理,也就是发送消息和接收消息不是同步的处理。 这种机制通常用来处理相对耗时比较长的操作。
Handler的工作流程
添加图片注释,不超过 140 字(可选)
Looper就像传送带传送消息,handler通过send/post方法,将货物送上传送带,这些货物就是message,排成messageQueue。当Looper.loop()调用,就是给传送带插上了电,无休止地转动,当传送到那一头了,就通过handler.dispatch()方法传递给需要货物的地方。
原理
简单概括一下:
Handler创建时会采用当前线程的Looper来构建内部的消息循环系统如果当前线程没有Looper那么就会报错,因此使用时主要为当前线程创建Looper即可或者在一个有Looper的线程中创建Handler也可以,在我们的UI线程中系统已经在一开始就为我们创建好了,自定义的子线程如何创建后面会说。
首先需要搞定几个概念
【MessageQueue】是一种数据结构,见名知义,就是一个消息队列(注意不是数据结构的队列,其实是个单链表),存放消息的地方。每一个线程最多只可以拥有一个MessageQueue数据结构。创建一个线程的时候,并不会自动创建其MessageQueue。通常使用一个Looper对象对该线程的MessageQueue进行管理。主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个Message Queue。其他非主线程,不会自动创建Looper,要需要的时候,通过调用prepare函数来实现。
示例:
[java] view plain copy
public void run(){
Looper.prepare(); //创建该线程的Looper对象
//这里Looper.myLooper()获得的就是该线程的Looper对象了
handler = new ThreadHandler(Looper.myLooper());
Message msg = handler.obtainMessage(1,1,1,"我自己");
handler.sendMessage(msg);
Looper.loop();
}
俩行代码,该线程就具有自己的Looper啦
【Message】消息对象
MessageQueue里面可以存放Message的消息一个Message Queue中包含多个Message。Message实例对象的取得,通常使用Message类里的静态方法obtain(),该方法有多个重载版本可供选择;它的创建并不一定是直接创建一个新的实例,而是先从Message Pool(消息池)中看有没有可用的Message实例,存在则直接取出返回这个实例。
[java] view plain copy
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
源码中可以看出如果Message Pool中没有可用的Message实例(poolsize=50),则才用给定的参数创建一个Message对象。调用removeMessages()时,将Message从Message Queue中删除,同时放入到Message Pool中。除了上面这种方式,也可以通过Handler对象的obtainMessage()获取一个Message实例。
通常Message Queue只有俩种单链表操作 插入(对应方法enqueueMessage)和读取(next)
【Looper】
是MessageQueue的管理者。每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的。同时每一个Looper对象和一个线程关联。通过调用Looper.myLooper()可以获得当前线程的Looper对象创建一个Looper对象时,会同时创建一个MessageQueue对象。除了主线程有默认的Looper,其他线程默认是没有MessageQueue对象的,所以,不能接受Message。如需要接受,自己定义一个Looper对象(通过prepare函数),这样该线程就有了自己的Looper对象和MessageQueue数据结构了。Looper从MessageQueue中取出Message然后,交由Handler的handleMessage进行处理。处理完成后,调用Message.recycle()将其放入Message Pool中。
Looper扮演着消息循环角色,一有消息就处理,否则就阻塞在那里。
本文主要是对在Android开发中,Handler的原理机制的解析。Handler在Android开发中处于非常重要的技术之一。更多有关Handler的技术或者高级Android开发,可以参考《Android核心开发手册》点击可以查看详细类目。