1.Message:消息实现Parcelable以便在进程间传输数据,包含消息标志,以及要传输的消息类型,一般是以Bundle来进行数据的传输,当然Message也定义了两个额外的int和一个Object来进行。
2.MessageQueue:消息队列,存放消息的容器,已FIFO(先进先出)算法来存取消息
3.Handler:处理者,关联一个线程和一个MessageQueue队列,负责Message对象的发送和处理,我们可以重写handleMessage回调接口方法来对Message对象进行处理和更新UI组件
4:Looper:消息泵,循环的从MessageQueue消息队列中读取消息,调用Handle的dispatchMessage来处理消息
我们用一个例子来分析Handler机制的运转流程
我们一般使用Handler的使用是一般是这样写的在MainActivity中我们声明一个Handler对象并重写其handleMessage回调方法来接收Looper从MessageQueue消息队列中读取的Message消息并更新UI组件。
Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
/**
* 接收消息并处理
* switch(msg.what){
* case xx:
* break;
* }
*/
super.handleMessage(msg);
}
};
在线程中我们一般是这样使用Handler发送消息给主线程的
mHandler.sendMessage(mHandler.obtainMessage(1));
现在我就来带大家从源码的角度来分析下Handler的流程,从而使大家对Handler的机制有个比较清楚的了解。
首先,追踪mHadnler.sendMessage(mHandler.obtainMessage(1))方法,发现其Handler源码是函数是
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
继续追踪sendMessageDelayed(Message msg, long delayMillis)函数
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);//在当前时间delayMillis
//毫秒后push消息到MessageQueue队列中
}
继续追踪sendMessageAtTime(Message msg, long uptimeMillis)函数:
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;//得到当前的消息队列
if (queue != null) {
msg.target = this;//记住当前的Handler
sent = queue.enqueueMessage(msg, uptimeMillis);//交由MessageQueue队列对Message对象进行处理
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
这里我们要明白MessageQueue queue = mQueue;这个mQueue对象是哪里来的,又是什么时候创建的,这时我们追踪mQueue对象,我们可以发现当我们创建Handler对象时对它进行赋值的:
public Handler() {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = null;
}
在Handler类提供的几个构造函数里都有着这句语句,来对mQueue 进行赋值
mQueue = mLooper.mQueue;
这时我们追踪mLooper时可以发现,其mLooper是一个Looper对象,这时我们去追踪Looper类对象,发现Looper类是这样描述的:
* Class used to run a message loop for a thread. Threads by default do
* not have a message loop associated with them; to create one, call
* {@link #prepare} in the thread that is to run the loop, and then
* {@link #loop} to have it process messages until the loop is stopped.
意思就是为线程创建一个消息循环,循环的读取消息,直到停止循环
到这个,我们就可以下个结论:Handler的消息是由Looper来进行循环读取的?结论真是这样吗?
我们查看Looper源码的时候,发现Looper是通过prepare来初始化当前线程的消息泵,并将Looper与Handler进行关联,然后通过loop来运行线程的消息队列来循环的读取消息,这里我们查看源码:
public static void loop() {
final Looper me = myLooper();//取得Looper对象
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;//关联消息队列
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();//复位IPC的当前线程的身份标识
for (;;) {//循环读取消息
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);//
msg.taget是什么呢?通过前面的Handler分析:
msg.target = this;//记住当前的Handler可以发现msg.taget为Handler对象(设计Handler的人既然用msg来记住Handler,高),所以说这句话就是交由Handler的dispatchMessage函数去处理消息
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycle();
}
}
Ok通过分析loop函数源码,我们发现,Handler的消息确实是通过Looper来循环读取,并交于Handler的dispatchMessage来进行处理。细心的同学可能会发现,loop源码中有句语句是讲looper和MessageQueue进行关联的语句,那就是:
final MessageQueue queue = me.mQueue;//关联消息队列的,这时,我们就要有个疑问了,我们什么时候把Looper对象和MessageQueue 关联起来的,我们追踪mQueue发现这样一个方法
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mRun = true;
mThread = Thread.currentThread();
}
这里发现是在Looper的构造函数进行对MessageQueue对消息队列进行创建,当然这里也可以发现Looper的构造函数是个private的,也就是说,此Looper类被设计成一个单例模式,已确保一个线程只有一个Looper来对MessageQueue进行循环的读取消息的。我们在查看下Looper类的定义发现:
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper; // guarded by Looper.class
final MessageQueue mQueue;
final Thread mThread;
volatile boolean mRun;
private Printer mLogging;
结合前面的分析,我们可以下个定义,Looper在维护着当前线程的MessageQueue的消息队列,通过loop函数对MessageQueue队列循环的读取消息,并交于Handler(通过Message.target来获取)的dispatchMessage函数进行处理,所以现在我们就清楚了Message,MessageQueue,Handler,Looper之间的关系,现在的我们只是还差一步,就是我们为什么重写handleMessage就可以来接收消息,对消息进行处理呢?这时,我们就分析Handler的dispatchMessage方法:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {//Message的Runnable对象是否存在,存在就交于handleCallback函数处理
handleCallback(msg);
} else {
if (mCallback != null) {//mCallback 不等于空,
查看源码可以得知mCallback 为 public interface Callback {
public boolean handleMessage(Message msg);
}Callback 接口对象
if (mCallback.handleMessage(msg)) {//交于mCallback 的回调函数处理
return;
}
}
handleMessage(msg);//交于handleMessage函数处理,查看Handler可以发现其源码提供了一个handleMessage函数的空实现方法
public void handleMessage(Message msg) {
}所以说,只要我们在创建Handler对象的时候,重写了handleMessage方法,我们就可以接收到Message消息,哈哈,现在我们终于知道为什么我们可以在handleMessage函数中接收Message对象了
}
}
到现在为止,我们就把Message,MessageQueue,Handler,Looper分析完了,相信大家对Handler的机制应该有个比较清楚的认识了,这里我给Handler机制来下个定义:通过Handler来push消息到MessageQueue,由Looper对象来循环读取MessageQueue消息队列,取得Message对象,通过Message对象的Handler对象的dispatchMessage方法来向Hanlder传递Message消息