一.什么是Handler
Handler是Android机制的一个上层接口,Handler通过发送和处理Message和Runnable对象来关联相对应线程的MessageQueue。
1.可以让对应的Message和Runnable在未来的某个时间点进行相应处理
2.让想要处理的耗时操作放在子线程。让更新UI的操作放在主线程
二.Handler使用方法
1.post(runnable)和sendMessage(message)
这俩个方法都是返回了sendMessageDelayed();
区别是post返回的sendMessage里的参数,是通过getPostMessage方法把Runnable对象设置给了Message的callback字段,最后将Message对象插入消息队列
private static Message getPostMessage(Runnable r) {
//获取一个message,把Runnable封装成了一个Message对象
Message m = Message.obtain();
m.callback = r;
return m;
}
而sendMessage方法因为他的参数是message对象,不需要转换直接就能存到消息队列中.
三.Handler机制
Looper:是每一个线程中所独有的,用来为一个线程开启一个消息循环,它通过它的loop()方法读取它下面MessageQueue的消息,读取到消息后把消息发送给Handler来进行处理。
MessageQueue:是一个消息队列,它是一个先进先出的方式来管理的
在创建Looper的时候,其实它已经创建了MessageQueue,所以创建Looper的时候,Looper和MessageQueue已经关联到了一起。
Message:是消息对象,它里面有很多参数(what,arg1,arg2,obj(可以传一些复杂的对象))
Handler:它有两个作用,发送消息和处理消息,处理Looper发送过来的消息,Looper发送消息也是通过Handler来进行的,Handler发送消息不是漫无目的发送,它不能发送到其他线程,它只能发送到它相关线程的MessageQueue当中,而MessageQueue又是和Looper关联的,所以说Handler要发送消息必须有一个维护它的Looper,这时候就把Looper,MessageQueue,Handler关联到了一起
我们在创建Handler时,他的构造方法已经通过Looper.myLooper()创建好了Looper实例,并通过创建好的Looper对象的mQueue创建一个MessageQueue实例
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());
}
}
//创造了Looper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//通过Looper创造了MessageQueue
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
这样Handler和MessageQueue关联到一起,而MessageQueue又是Looper管理的.
myLooper方法是通过ThreadLocal.get()获取,
ThreadLocal 线程本地存储区(Thread Local Storage) 通过不同的线程访问同一个ThreadLocal,不管是它的set()方法还是get()方法,它们对ThreadLocal所做的读写操作仅限于各自线程的内部。也就是不同线程彼此不能访问对方的ThreadLocal。
这就是Handler里为什么要通过ThreadLocal来保存Looper,这样它就可以使每一个线程有单独唯一的Looper。
Looper.prepare()方法中的“ sThreadLocal.set(new Looper(quitAllowed))”,就是它创建了一个Looper对象,并且把这个Looper对象设置给了ThreadLocal,保证了每一个线程Looper的唯一性。Looper内部维护一个MessageQueue。
这时候整个的MessageQueue通过Looper跟线程关联上了,这样不同的线程就不能访问其他的消息队列了。Looper内部维护一个MessageQueue。
这时候整个的MessageQueue通过Looper跟线程关联上了,这样不同的线程就不能访问其他的消息队列了
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
而从MessageQueue队列中获取消息,要通过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;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final long traceTag = me.mTraceTag;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
try {
//处理消息
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
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.recycleUnchecked();
通过代码可以看出,loop()方法实际上就是创建了一个for的死循环,然后从消息队列中逐个获取消息(当没有消息时,queue.next()会阻塞,直到有消息才继续执行),最后处理消息的过程。
总结一下:Looper通过Looper.prepare()来创建Looper对象,保存在ThreadLocal中,然后通过Looper.loop()开启循环,来进行消息的分发
msg.target.dispatchMessage(msg)也就是Handler.dispatchMessage(msg)
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
dispatchMessage(msg)方法其实只是一个分发的方法,首先会判断msg.callback是否为空,(.callback其实是一个Runnable对象,在上面的使用方法中有写)如果不为空,就执行handleCallback方法,而handleCallback方法里面其实调用的就是线程的run()方法。如果为空,将执行handleMessage来进行处理。