消息驱动是一种进程或线程的运行模式。内部、外部的各种事件可以放到消息队列中按序处理。比如:Android的应用UI线程。
在windows的消息处理模型中,只有一个系统消息队列,这个队列是整个进程的核心,几乎所有动作都要转换成消息,放到这个队列中,消息处理在主线程完成。
也就是有多个线程发送消息,只有一个属于进程的消息队列,以及只有一个主线程处理消息队列中的消息。
Android的消息处理不一样。Android没有全局的消息队列,消息队列是和某个线程相关的。每个线程最多只有一个消息队列,消息的取出和处理也在线程中完成。
也就是有多个线程发消息,有多个消息队列在不同的线程中,分别在各自的线程中处理消息。
Windows的消息模型比较简单,但是全局的消息队列容易成为程序的瓶颈。
Looper类
looper是线程的消息循环处理器,每个线程只能有一个Looper对象,其内部有一个MessageQueue,所有消息都存放在这个队列中。新创建一个线程时,系统不会为这个线程创建Looper,需要自己创建。Android在启动时,为主线程(UI线程——创建了一个looper对象)。
我们先看一下HandlerThread线程,其就是继承了一个普通的线程,提供了一个消息队列和消息相应代码的运行环境。
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();//Looper类的实例必须通过prepare函数创建
synchronized (this) {
mLooper = Looper.myLooper();//通过myLooper方法获取Looper对象
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();//loop函数主要分发消息队列中的消息。
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
}
下面我们主要看下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;//消息队列
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {//无线循环
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
........
msg.target.dispatchMessage(msg);//分发消息
......
msg.recycle();
}
}
Handler类
Handler主要负责消息的发送和处理。在一个线程中可以只用一个Hander对象处理所以消息,也可以使用多个。
构造一个Handler对象,需要两个参数,线程的Looper对象和消息处理函数,如果不指定looper,会使用当前线程的looper对象
Handler发送消息的接口如下:
public final boolean sendMessage(Message msg)//不插队
{
return sendMessageDelayed(msg, 0);
}
public final boolean sendEmptyMessage(int what)//只有一个消息ID
{
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
Message msg = Message.obtain();//指定时间,只有消息ID,其实就是自己获取一个msg,再调用sendMessageAtTime
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)//延迟多少时间
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
public final boolean sendMessageAtFrontOfQueue(Message msg) {//非常紧急,希望尽快处理
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, 0);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;//注意msg.target都是handler,因此在消息线程的loop函数处理消息时,msg.target.dispatchMessage会回到handler。
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
所有的发送消息接口,最后都会调用MessageQueue类中enqueueMessage函数,参数除了消息外,就是一个时间。而MessageQueue类中enqueueMessage函数只是把消息插入到消息队列中的合适位置。
我们再来看看Handler类的一些Post类型的函数:
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postAtTime(Runnable r, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
public final boolean postDelayed(Runnable r, long delayMillis)
{
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
public final boolean postAtFrontOfQueue(Runnable r)
{
return sendMessageAtFrontOfQueue(getPostMessage(r));
}
也是调用的send函数,只是调用了getPostMessage函数:
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
创建了一个message对象,并且将Runable对象赋给了callback。
下面再来看看Handler对象的dispatchMessage就知道了:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);//如果msg自带了callback函数
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);//最后再调用Handler的handleMessage函数
}
}
看看handleCallback函数就是调用了msg的回调函数:
private static void handleCallback(Message message) {
message.callback.run();
}
Handler中removeMessages将消息队列中的消息去除:
public final void removeMessages(int what, Object object) {
mQueue.removeMessages(this, what, object);
}
最后总结下:首先消息机制需要一个线程环境,里面需要一个Looper对象,并且在线程的run函数中调用Looper.loop()函数。函数需要一个handler来发送和处理消息。Hander要有一个Looper对象,来指定其线程,还要实现handleMessage函数。