您的位置:首页 > 产品设计 > UI/UE

从源码中深入学习Handler,HandlerThread,MessageQueue,Looper。

2015-03-10 21:29 633 查看
今天在写项目时用到了HandlerThread,就顺便把Handler,MessageQueue,Looper都顺便复习整理了一下,写成博客,与大家分享,由于自己水平有限,难免理解的有些浅薄,有什么不合适或者不懂的地方欢迎留言询问,咱们一起探讨。

如果是对Handler一点都不了解的朋友,可以参考我的另一篇博客Handler:搭建UIThread&WorkerThread之间通信的桥梁

好了,下面我们进入正题。

HandlerThread其实就是一个Thread,只不过它初始化了相应的MessageQueue和Looper。这里听不懂没关系,我们继续往下看。

我们知道,如果是Handler,它初始化MessageQueue和Looper对象的方法是(下面的代码是需要用户写的)

new Thread(new Runable()){
@Override
public void run() {
new Handler(){
@Override
public void handleMessage(Message msg) {
Looper.prepare();
......    //处理消息的代码
Looper.loop();
}
}
}
}


而HandlerThread的run方法呢,是源码中写好的

public class HandlerThread extends Thread {
int mPriority;     //线程优先级
int mTid = -1;     //线程的ID
Looper mLooper;    //该线程对应的Looper对象

public HandlerThread(String name) {  //name  该线程的名字
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
//HandlerThread的另一个构造函数
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
//下面是该线程的run()方法
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
//重点:HandlerThread的run()方法调用了looper.prepare()方法,初始
//化了Looper和MessageQueue,至于为什么,下面再讲解
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
//重点:HandlerThread的run()方法调用了looper.loop()方法,建立了消
//息队列的循环
mTid = -1;
}
}


总结一下,就是HandlerThread比Handler+Thread的方式更方便,因为它自己已经初始化好了Looper和MessageQueue,用户直接调用handler.obtainMeaasge()发送消息,用handler.handleMessage()出息消息就行了,而且不用重写(Override)run()方法。

下面说一下为何通过Looper.prepare()可以初始化Looper和MessageQueue,还是让我们从源码中找答案。

先看怎样创建的Looper对象。

public static void prepare() {
prepare(true);
}
//我们可以看到,调用Looper.prepare()方法后直接调用了prepare(true)
//方法,而在该方法中很明显,new Looper(quitAllowed)新创建了一个
//Looper对象,
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对象
}


再看怎样初始化的MessageQueue。


private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);//重点:这里新创建了一个MessageQueue。
mRun = true;
mThread = Thread.currentThread();
}


细心的朋友可能会问,Handler,Looper,MessageQueue是怎样绑定在一起的呢,我这里贴一下Looper类的几个成员变量,大家就明白了。

private static final String TAG = "Looper";

// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper;  // guarded by Looper.class

final MessageQueue mQueue;   //Looper对象的MessageQueue
final Thread mThread;        //Looper对象的Thread
volatile boolean mRun;

private Printer mLogging;


至于怎样绑定Handler对象,看了HandlerThread的用法,就一目了然了,下面讲解HandlerThread的基本用法。

handlerThread=new HandlerThread("HandlerThreadName->Login");
handlerThread.start();
handler(handlerThread.getLooper());
handler=new Handler(handlerThread.getLooper()){//怎么样,绑定了吧,这是HandlerThread的最基本的用法,网上基本都是讲的这个。
@Override
public void handleMessage(Message msg) {
}
}


**下面让我们进行一下最后的总结:

1.HandlerThread=MessageQueue+Looper+Thread

2.HandlerThread+Handler=MessageQueue+Looper+Thread+Handler

3.对于一个Thread,对应着一个唯一的MessageQueue,唯一的Looper,一个或者多个Handler对象。**

好了,想必大家已经明白的差不多了吧,由于本人水平实在有限,只能讲到这样了,有什么不明白的欢迎留言询问,大家一起探讨,今天就到这里了,再见。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐