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

来源:互联网 发布:java 对象流 编辑:程序博客网 时间:2024/05/16 19:32

今天在写项目时用到了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对象。**
好了,想必大家已经明白的差不多了吧,由于本人水平实在有限,只能讲到这样了,有什么不明白的欢迎留言询问,大家一起探讨,今天就到这里了,再见。

0 0