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

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

2015-04-11 00:06 267 查看
权利声明:转载请注明出处:/article/1805814.html

今天在写项目时用到了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对象。**

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