- 论坛徽章:
- 0
|
Android101104 android.os包的简记(1): Handler
Email: zcatt@163.com Blog http://zcatt.cublog.cn
内容提要 文档简要整理android.os包的内容。以供备忘和参考。
声明 仅限学习交流,禁止商业用途。转载需注明出处。
版本记录 Date Ver Note 2011-01-04 0.1 Draft. zcatt, Beijing 1. Handler机制 Handler机制属于异步处理。典型的例子, 非ui线程要更新ui, 那么不应当直接操作ui的更新,而是应当将更新事件发送到ui的线程中,由ui线程进行更新ui操作。 更新事件中可以包括更新的方法或者回调。 android.os包中的Handler机制相关的类文件包括 Handler.java MessageQueue.java Message.java Looper.java HandlerThread.java Message用于封装事件消息,Looper代表了处理事件消息的循环。MessageQueue是个事件消息队列,接收的消息在这里排队,等待Looper的处理。HandlerThread是一个辅助类,用于方便创建带有looper的thread。 如图<android_os_handler> 下面分述之。
2.Message Message封装的是事件消息。包含的属性主要有, Handler target; Runnable callback; long when; public int what; public int arg1; public int arg2; public Object obj; Bundle data; 其中,target和callback通常只有一个有效,用于说明谁(Handler)处理这个message或者使用什么回调(Runnable)来处理。如果message设定了callback,那么在处理message时将使用callback,而不使用Handler,但一般的使用方法都是设定Handler,使用Handler::handleMessage()处理消息。what, arg1, arg2, obj,和data是事件消息的具体内容,message的发送者和接收处理者可以通过这些传递信息,决定处理的动作。 特别注意,对于process间的传递message,obj必须是支持Parcelable的,而data应该使用Bundle.setClassLoader()设置了classLoader。 简而言之,Message对象中包含了谁处理(target,callback),处理什么(what,arg1,arg2,obj,data),和时间(when)的信息。 为了加速Message的分配和释放,Message维持了一个类message缓冲池,释放的message会放到缓冲池中,当申请新的message时,直接从缓冲池中取用。Message中有一个next域,可以用于链接message。
3.MessageQueue MessageQueue是一个消息队列,message按照时间顺序在队列中排列,给定时间,可以方便的从队列中得到指定时间前的时间。MessageQueue的关键方法是 final Message next(); final Message pullNextLocked(long now); next()返回队列中最前的message. pullNextLocked()返回指定时间以前的队列中最前的message.
4.Looper Looper是handler机制的核心,它代表的是thread中的事件处理循环。一个thread通常按照下面的方式组装进Looper,就构成了真正处理message的thread。
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } } Looper对象生成并关联唯一一个MessageQueue,消息事件message被投递到MessageQueue,而真正的处理loop()方法则运行在自己的thread中,从MessageQueue中依次取出message进行派发处理,记得message中包含有“谁处理”的信息。 几个关键方法, public static final void prepare(); public static final void loop(); public static final Looper myLooper(); public void quit(); 注意前3个方法是static。Looper是运行在自己的thread中的,Looper使用了ThreadLocal来保存自己线程关联的(使用的)Looper对象,这也是prepare(),loop(),和myLooper()是static的原因。也就是说perpare(),loop()和myLooper()应该使用在自己的线程中。 prepare()负责创建一个looper对象,并保存在ThreadLocal变量中。 loop()负责实际的读取messageQueue并分发处理,实际是一个循环,出口条件是碰到一个target是null的message。这也是正常的message的target必须与一个handler关联,不能为0的原因。 myLooper()可以得到当前线程对应的looper对象,当然调用myLooper()前应当保证prepare()已经执行了。 quit()方法就是用于退出loop()的消息循环,从而结束处理线程。实现的方法就是构造一个target为null的message,并加入messageQueue
5.Handler Handler必然跟一个Looper对象相关联,也就是跟一个messageQueue相关联。创建时,如果不指定,则默认是当前线程对应的Looper。 每个message都会跟一个Handler关联。Handler提供消息的处理方法。开发中需要继承Handler类,在派生类中通常实现handleMessage()方法。在handleMessage()中实现处理message的逻辑,handleMessage()会在Looper.loop()中被分发调用,处理message。当然如果message指定了callback,将使用callback方法处理message。 Handler是Handler机制中的编程接口,一般情况下,开发中无需关注Looper,MessageQueue,只要使用Handler就够了。 Handler还提供了几个obtainMessage()方法,便于开发者申请分配message对象,当然得到的message对象都已经跟Handler关联好了。 开发者申请分配message,得到message对象后,设定message的各信息域。接下来就是发送到messageQueue中,这个可以通过几个sendMessage和postMessage进行。send和post的区别在于,send的消息将使用Handler的handleMessage()方法处理message,而post将定义callback,使用callback处理message。下面罗列这些send,post方法,不详述。 public final boolean post(Runnable r); public final boolean postAtTime(Runnable r, long uptimeMillis); public final boolean postAtTime(Runnable r, Object token, long uptimeMillis); public final boolean postDelayed(Runnable r, long delayMillis); public final boolean postAtFrontOfQueue(Runnable r); public final boolean sendMessage(Message msg); public final boolean sendEmptyMessage(int what); public final boolean sendEmptyMessageDelayed(int what, long delayMillis); public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis); public final boolean sendMessageDelayed(Message msg, long delayMillis); public boolean sendMessageAtTime(Message msg, long uptimeMillis); public final boolean sendMessageAtFrontOfQueue(Message msg);
6.HandlerThread HandlerThread是一个辅助函数,方便创建带有Looper的thread。
7. 使用方法
7.1自己新建专有消息处理thread的情况
1)使用HandlerThread创建looper thread
HandlerThread myLooperThread; myLooperThread = new HandlerThread("my looper thread"); myLooperThread.start();
2) 定义handler
class MyHandler extends Handler { public myHandler(Looper looper) { super(looper); }
public void handleMessage(Message msg) {
// to do your processing
} }
Looper looper = myLooperThread.getLooper(); MyHandler myHandler = new MyHandler(looper);
3)发送事件消息
Message msg; msg = myHandler.obtainMessage(...);
//set msg fields msg.what = ...; msg.arg1 = ...; ...
//send msg myHandler.sendMessage(msg);
//or
msg.sendToTarget();
7.2使用已有的thread,不创建自己的处理thread
1)定义handler
class MyHandler extends Handler { public myHandler(Looper looper) { super(looper); }
public void handleMessage(Message msg) {
// to do your processing
} }
Looper looper = Looper.myLooper(); MyHandler myHandler = new MyHandler(looper); 2)发送事件消息 同上,不赘述。  |
|