Handler机制
来源:互联网 发布:招标软件哪个好 编辑:程序博客网 时间:2024/06/07 06:11
Handler机制中涉及到几个比较重要的类:Handler、Looper、Message、和MessageQueue。UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper。使用ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。之后其他Handler初始化的时候直接获取第一个Handler创建的Looper。Looper初始化的时候会创建一个消息队列MessageQueue。Hander持有对消息队列MessageQueue和消息循环器Looper的引用,子线程可以通过Handler将消息Message发送到消息队列MessageQueue中。UI主线程通过Looper循环查询消息队列,当发现有消息存在时会将消息Message从消息队列中取出,将消息Message分发给相应的Handler进行处理。
对于Handler机制的源码分析分析文章很多,在此对源码就不多说了。下面通过自定义Hander 、Looper、 MessageQueue和 Message,加深大家对Handler机制的理解。
1.Handler类:类里有两个重要的成员变量MessageQueue mQueue和Looper mLooper,也就是,Handler被实例化的时候,持有MessageQueue和Looper 的引用,Handler中两个很重要的函数:sendMessage(Message msg)和handleMessage(Message msg),子线程发送消息时,调用前者,Looper从消息队列MessageQueue取出Message时,会调用handleMessage(Message msg)处理消息,所以我们在实例化Handler的时候,重写handleMessage(Message msg)函数,该函数就会被回调。
package mhandler;public class Handler { public MessageQueue mQueue;//消息队列 private Looper mLooper; public Handler() { mLooper = Looper.myLooper();//获取当前线程的looper对象 this.mQueue = mLooper.mQueue; } /** * 发送消息,把message对象加入消息队列 * @param msg */ public void sendMessage(Message msg){ msg.handler = this; //Message消息压入消息队列 mQueue.enqueueMessage(msg); } public void dispatchMessage(Message msg){ handleMessage(msg); } public void handleMessage(Message msg){ }}
2.Looper:消息轮询器。通过ThreadLocal存取Looper,每个线程只允许创建一个Looper,在UI主线程中,已经调用了prepare()函数实例化了一个Looper,所以不需要程序员去实例化looper,在最后也调用了loop()函数,开启轮询。若在子线程中实例化Handler对象,则需要先调用prepare()最后调用loop()函数。Looper的作用是不断地循环查询消息队列,当发现有消息存在时,会将消息Message从消息队列中取出,将消息Message分发给相应的Handler进行处理。
package mhandler;public final class Looper { //looper对象保存在ThreadLocal,保证了线程数据的隔离 static final ThreadLocal<Looper> mThreadLocal = new ThreadLocal<Looper>(); MessageQueue mQueue; private Looper(){ mQueue = new MessageQueue(); } /** * 初始化looper,将其加入mThreadLocal */ public static void prepare(){ if (mThreadLocal.get() != null) { throw new RuntimeException("一个线程只能拥有一个looper"); } mThreadLocal.set(new Looper()); } /** * 获取looper对象 * @return */ public static Looper myLooper(){ return mThreadLocal.get(); } /** * 轮询消息队列 */ public static void loop(){ Looper me = myLooper(); if (me == null) { throw new RuntimeException("looper空,请先调用prepare()实例化looper对象"); } MessageQueue queue = me.mQueue; for (;;) { Message msg = queue.next(); if (msg == null) { continue; } msg.handler.dispatchMessage(msg); } }}
3.Message:消息类,持有一个Handler 的引用
package mhandler;public class Message { public int what; public Object obj; Handler handler;}
4.MessageQueue:消息队列,以链表的数据结构存取Message,源码中Message对象还有时间when属性,默认情况下,Message的when为存储时的时间,若调用了sendMessageDelayed(Message msg, long delayMillis)函数,则when = 当前时间+delay的时间,MessageQueue会按照时间顺序把Message加入队列。
package mhandler;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class MessageQueue { Message[] items;//存放消息的数组 private int putIndex; private int takeIndex; private int count; //互斥锁 private Lock lock; private Condition notEmpty; private Condition notfull; public MessageQueue() { this.items = new Message[50]; this.lock = new ReentrantLock(); this.notEmpty = lock.newCondition(); this.notfull = lock.newCondition(); } /** * 子线程加入消息队列 * @param msg */ public void enqueueMessage(Message msg){ try { lock.lock();//枷锁 //消息队列已满,子线程阻塞,停止消息加入队列 while(count == items.length){ try { notfull.await(); } catch (InterruptedException e) { e.printStackTrace(); } } items[putIndex] = msg; //如果putIndex等于数组长度,则归零 putIndex = (++putIndex == items.length) ? 0 : putIndex; count ++; //通知主线程停止阻塞 notEmpty.signalAll(); } finally { lock.unlock(); } } /** * 主线程消息出队 * @return */ public Message next(){ try { lock.lock();//枷锁 //消息队列为空,主线程阻塞 while(count == 0){ try { notEmpty.await(); } catch (InterruptedException e) { e.printStackTrace(); } } Message msg = items[takeIndex]; items[takeIndex] = null; takeIndex = (++takeIndex == items.length) ? 0 : takeIndex; count --; //通知子线程停止阻塞 notfull.signalAll(); return msg; } finally { lock.unlock(); } }}
完整demo下载地址:http://download.csdn.net/detail/chen20142015/9800242
- Handler机制
- Handler机制
- handler机制
- handler机制
- Handler机制
- Handler机制
- handler机制
- Handler机制
- handler机制
- Handler机制
- handler机制
- Handler机制
- Handler机制
- Handler机制
- handler机制
- handler机制
- Handler机制
- Handler机制
- php 获取指定范围内指定数量的随机数
- jQuery的ajax方法
- 跟小博老师一起学习数据库 ——delete
- LAMP安装教程
- htaccess书写规则
- Handler机制
- Liunx 如何查看80端口被哪个程序所占用
- Java集合框架
- 代理模式之动态代理的实现——CGLib
- Hive时间是String格式截取字串和转换数据类型小贴士
- BufferedInputStream和BufferedOutputStream用法 解决乱码
- Eclipse导入项目出现 Android requires compiler compliance level 5.0 or 6.0. Found '1.4' instead. Please us
- C# 模板编程相关学习总结
- HDFS负载均衡问题