本文可以和另外一篇文章结合起来看,Android消息机制之——Handler Looper源码分析
在Handler源码开篇,惯例地,有关该类的说明。强烈建议阅读理解10遍+,比任何解说的文章都好用。这里只摘出重要的部分:
* A Handler allows you to send and process Message and Runnable
* objects associated with a thread's MessageQueue. Each Handler
* instance is associated with a single thread and that thread's message
* queue. When you create a new Handler, it is bound to the thread /
* message queue of the thread that is creating it -- from that point on,
* it will deliver messages and runnables to that message queue and execute
* them as they come out of the message queue.
1、Handler通过和一个线程的MessageQueue(俗称消息队列)关联,来进行Message、Runnable的发送和处理;
2、每个Handler实例对应唯一的一个线程以及这个线程对应的MessageQueue;依据Handler实例被创建方式的不同,Handler和创建它一个线程或者一个线程的MessageQueue进行绑定;
3、Handler将消息发送到它绑定的MessageQueue; 同时接收从MessageQueue中派发的消息并进行处理。
这里体现出了Handler的主要作用,即将消息切换到绑定的MessageQueue所在的线程里执行,而不管消息是从哪个线程发送过来的。
一、Handler创建方式:
根据是否指定Looper,分为两种:
(1)我们通常使用的方法,直接new Handler的形式;比如,在某个线程中:
class MyThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare(); //当前线程绑定一个MessageQueue
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
我们知道,Looper.prepare() 是为当前线程绑定一个Looper实例及MessageQueue,在new Handler时,用的就是当前线程的Looper实例和MessageQueue;
Looper的相关细节,可以参见另一篇文章,Android消息机制之——Handler Looper源码分析
调用的构造函数:
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
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 = callback;
mAsynchronous = async;
}
这里面比较核心的两句:
mLooper = Looper.myLooper(); //和当前线程的Looper实例相关联;mQueue = mLooper.mQueue; //和当前线程的Looper实例的MessageQueue相关联。
同时我们发现,构造函数里面是可以指定callback的,这个callback会在处理消息时,也就是dispatch函数里面用到。
而我们通常的做法,在一个Activity的onCreate()函数里面new Handler(),绑定的是主线程的Looper实例和MessageQueue。具体代码可看ActivityThread源代码。
(2) 指定Looper,这是Handler不太常用的,比较特殊的构造方法,通过这种方法,Handler将和指定的Looper以及Looper的MessageQueue进行绑定;
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
二、Handler两大作用:发送消息 处理消息
发送消息的方法有:
post Runnable方式: post, postAtTime(Runnable, long), postDelayed;
send Message方式: sendEmptyMessage, sendMessage, sendMessageAtTime, sendMessageDelayed;
Runnable对象最终也是被包装成Message对象发送到Handler所绑定的MessageQueue中去:
Runnable 会被包装成设有callback的Message对象:
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
最终发送消息的方法:
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);
}
将消息插入到消息队列中去,并且将消息的target设为本Handler实例(this):
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
我们知道,Handler绑定了一个Looper实例,loop方法会不停地从MessageQueue.next()中看是否有消息,如果有消息,就去调用msg.target.dispatchMessage()进行处理,也就是message对应的Handler实例的dispatchMessage()方法进行处理:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg); // post一个Runnable,Runnable设有callback
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) { //构造函数传入callback
return;
}
}
handleMessage(msg); // 重写Handler的handleMessage()方法
}
}
三、推荐使用obtainMessage方法去获得一个消息对象
我们一般会这样创建一个Message:
Message msg = new Message();
msg.what = xxx;
msg.arg1 = xxx;
msg.arg2 = xxx;
handler.sendMessage(msg);
然而查看源码会发现, obtainMessage方法是获取一个Message对象效率更高的方式:
/*** Returns a new {@link android.os.Message Message} from the global message pool. More efficient than* creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).* If you don't want that facility, just call Message.obtain() instead.*/
使用obtainMessage()方法,是从全局的MessagePool中去拿一个Message, 而不是重新创建一个,省去了创建对象申请内存的开销。
因此应尽量使用:
Message msg = handler.obtainMessage();
而不要使用:
Message msg = new Message();
参考:
任玉刚 Android开发艺术探索
http://blog.csdn.net/singwhatiwanna/article/details/48350919
网友评论