本文参考http://blog.csdn.net/lmj623565791/article/details/43452969 hongyang大神的文章… 加入了一些自己的解读…
对于Handler Looper Message 之前一直只是知道理论,知其然不知所以然,看了hongyang大神的源码分析,写个总结帖.
一.概念..
Handler 、 Looper 、Message 这三者都与Android异步消息处理线程相关的概念。
异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环。若消息队列为空,线程则会阻塞等待。
说了这一堆,那么和Handler 、 Looper 、Message有啥关系?其实Looper负责的就是创建一个MessageQueue,然后进入一个无限循环体不断从该MessageQueue中读取消息,而消息的创建者就是一个或多个Handler 。
二.源码分析
说道Handler也是面试常客了… 当然这也是Android中比较重要的一个部分。
就按他们出场的先后顺序来分析吧(源码基于API 19,建议边看边根据源码对照)
Looper
最先是Looper… 为什么不是Handler? 这个问题和为什么主线程中我们没有调用Looper.prepare()的回答其实是一样的…
…App启动时 已经调用Looper.prepare()方法
那么我们来看看Looper.prepare()是做什么的呢..
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));
}
如果当前线程当中已经有Looper了 就抛出异常(这也是为什么一个线程只能有一个Looper实例 ,只有一个MessageQueue实例的原因) ;
如果没有就初始化一个Looper对象放入当前线程中
说明一下:sThreadLocal是什么..看源码便知 是用来存放当前当前线程的Looper对象的
static final ThreadLocalsThreadLocal = new ThreadLocal();
再看看Looper的构造方法
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mRun = true;
mThread = Thread.currentThread();
}
构造方法中,最主要的就是创建了一个MessageQueue,这东西是干嘛用的呢? 存放Handler发来的消息(接下来会证实),所以俗称 消息队列。
继续看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;
拿到当前线程中的Looper实例(如果Looper实例为空就会抛出异常)再去拿Looper中的MessageQueue实例
for (;;) {
Message msg = queue.next();
if (msg == null) {
return;
}
msg.target.dispatchMessage(msg);
msg.recycle();
}
依然只上了关键代码…
一个无限循环 不断从MessageQueue实例中获取下一个Message,未获取到便返回;
获取到Message实例则调用msg.target.dispatchMessage(msg); 把消息交给Message实例的target的dispatchMessage方法处理,看到这里可能会有疑问了,msg的target是什么? 查看源码可以发现就是Handler对象,下面分析Handler的时候会说道;最后释放msg
小结:Looper的主要作用
1.与当前线程绑定,并保证一个线程中只有一个Looper实例,从而保证了一个线程中只有一个MessageQueue实例。
2.loop()方法,就是不断的从MessageQueue中取出消息,并交给msg.target.dispatchMessage(msg)去处理(交给Handler去处理,接下来会细说)
Handler
我们用Handler之前都会初始化一个Handler对来更新UI线程…等等. 上源码. 来看看Handler是如何与MessageQueue关联上的 ,还有在非UI线程中是如何将消息发送到MessageQueue当中去的
来看看Handler的构造方法
public Handler(Callback callback, boolean async) {
// 省略相关检查代码
mLooper = Looper.myLooper(); // Tag1
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue; //Tag2
mCallback = callback;
mAsynchronous = async;
}
Tag1 调用了Looper.myLooper() 前面Looper分析环节说到了 这是从当前线程中拿出Looper实例
Tag2 将Looper实例中的MessageQueue实例取出来
此时,Handler和MessageQueue就关联上了
辣么? 我们我们在非UI线程中,是如何将消息传递给MessageQueue的呢… 继续看源码
平时通过Handler发送一条Message是不是通过
public final boolean sendMessage(Message msg){
return sendMessageDelayed(msg, 0);
}
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);
}
看到这里,大家想起了什么? 没错 mQueue就是Handler初始化的时候 从当前线程取出的Looper中取出来的MessageQueue
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
msg.target = this; ?? msg.target赋值为this,(大家还记得在前面Looper.loop()方法中不断从消息队列中读消息 然后调用 msg.target.dispatchMessage(msg)来处理信息 ) ;也就是将当前Handler实例作为msg的target属性,最终调用了queue.enqueueMessage(msg, uptimeMillis)方法 将消息存入MessageQueue中去 ; 换一句话说 Handler发出来的消息 最终保存到了MessageQueue中去
现在消息已经存入了MessageQueue中,前面提到Looper.loop() 会不断的读取MessageQueue中有无信息,有信息会通过msg.target(也就是Handler) 来调用dispatchMessage(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);
}
}
最后调用了handleMessage(msg); 看到这里是不是感觉很熟悉了 我们再快看看handleMessage(msg)的源码
public void handleMessage(Message msg) {
}
里面什么都没有? 什么情况? 回想一下,平时我们初始化一个Handler实例 是不是都会复写handleMessage方法? 因为最终回调是由我们来控制。说道这里 整个异步消息处理的流程已经梳理完了 让我们来总结一下
1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。
内容参考Hongyang大神的博客… 概念和总结属于搬运工… 源码分析属于二次加工,加上了一些自己的理解… 今天正好代码重构完成… 忙里偷闲写了这篇总结帖… 希望对大家在学习Android的道路上 有所帮助…