Android 中 Handler,Looper,HandlerThread 的关系分析

来源:互联网 发布:仆の知らない母磁力 编辑:程序博客网 时间:2024/06/08 12:15

Android 中 Handler,Looper,HandlerThread 的关系分析

最近项目中要用到 HandlerThread,对其的用法一直不甚了解,趁着五一放假就花了点时间研究一下,顺便备份在博客上。

因为刚开始研究的是 HandlerThread,所以我们就从 HandlerThread 入手,我们先来看一下它的源代码

/* * Copyright (C) 2006 The Android Open Source Project */package android.os;/** * Handy class for starting a new thread that has a looper. The looper can then be  * used to create handler classes. Note that start() must still be called. */public class HandlerThread extends Thread {    int mPriority;//线程优先级    int mTid = -1;//TID    Looper mLooper;//Looper成员变量    public HandlerThread(String name) {        super(name);        mPriority = Process.THREAD_PRIORITY_DEFAULT;//构造函数,设置默认线程优先级    }        /**     * Constructs a HandlerThread.     */    public HandlerThread(String name, int priority) {        super(name);        mPriority = priority;//构造函数,根据参数设置线程优先级    }        /**     * Call back method that can be explicitly over ridden if needed to execute some     * setup before Looper loops.     */    protected void onLooperPrepared() {//主要提供给子类,让子类去重写    }    public void run() {//run方法,终点来了        mTid = Process.myTid();//获取TID        Looper.prepare();//后面在Looper类里看        synchronized (this) {//同步            mLooper = Looper.myLooper();//后面在Looper类里看            notifyAll();//唤醒持有该对象的并且wait的线程        }        Process.setThreadPriority(mPriority);//设置线程优先级        onLooperPrepared();//HandlerThread类里没有实现,子类可以实现,做一些预处理操作        Looper.loop();//后面在Looper类里看        mTid = -1;    }        /**     * This method returns the Looper associated with this thread. If this thread not been started     * or for any reason is isAlive() returns false, this method will return null. If this thread      * has been started, this method will block until the looper has been initialized.       * @return The looper.     */    public Looper getLooper() {        if (!isAlive()) {//如果线程死掉了,返回null            return null;        }                // If the thread has been started, wait until the looper has been created.        synchronized (this) {            while (isAlive() && mLooper == null) {//如果线程活着,但是为null,就一直等待,与run方法里面的synchronized相一致                try {                    wait();//当线程没有被start(start之后才会alive)或者没有获取到Looper对象时wait。注意run方法中有notify操作。                } catch (InterruptedException e) {                }            }        }        return mLooper;//返回Looper成员变量    }        /**     * Ask the currently running looper to quit.  If the thread has not     * been started or has finished (that is if {@link #getLooper} returns     * null), then false is returned.  Otherwise the looper is asked to     * quit and true is returned.     */    public boolean quit() {        Looper looper = getLooper();        if (looper != null) {            looper.quit();//后面在Looper类里看            return true;        }        return false;    }        /**     * Returns the identifier of this thread. See Process.myTid().     */    public int getThreadId() {//返回TID        return mTid;    }}

源代码不是很多,有些涉及到Looper类里面的方法,我们再来看一下Looper类的源代码(只分析涉及到的方法和成员变量)。

/* * Copyright (C) 2006 The Android Open Source Project */package android.os;import android.util.Log;import android.util.Printer;import android.util.PrefixPrinter;public class 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>();    final MessageQueue mQueue;    final Thread mThread;    volatile boolean mRun;    private Printer mLogging = null;    private static Looper mMainLooper = null;  // guarded by Looper.class     /** Initialize the current thread as a looper.      * This gives you a chance to create handlers that then reference      * this looper, before actually starting the loop. Be sure to call      * {@link #loop()} after calling this method, and end it by calling      * {@link #quit()}.      */    public static void prepare() {        if (sThreadLocal.get() != null) {            throw new RuntimeException("Only one Looper may be created per thread");        }        sThreadLocal.set(new Looper());//把和当前线程相关的Looer变量(参考Looper构造方法)放进sThreadLocal中    }    /**     * Run the message queue in this thread. Be sure to call     * {@link #quit()} to end the loop.     */    public static void loop() {        Looper me = myLooper();//获取和当前线程相关的Looper变量        if (me == null) {            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");        }        MessageQueue queue = me.mQueue;//和当前线程相关的Looper变量的MessageQueue                // Make sure the identity of this thread is that of the local process,        // and keep track of what that identity token actually is.        Binder.clearCallingIdentity();        final long ident = Binder.clearCallingIdentity();                while (true) {//死循环哟,不过没关系,在MessageQueue中有处理,涉及到wait和notify,可以去MessageQueue中探究。            Message msg = queue.next(); // might block,获取Message            if (msg != null) {                if (msg.target == null) {                    // No target is a magic identifier for the quit message.                    return;                }                long wallStart = 0;                long threadStart = 0;                // This must be in a local variable, in case a UI event sets the logger                Printer logging = me.mLogging;                if (logging != null) {                    logging.println(">>>>> Dispatching to " + msg.target + " " +                            msg.callback + ": " + msg.what);                    wallStart = SystemClock.currentTimeMicro();                    threadStart = SystemClock.currentThreadTimeMicro();                }                msg.target.dispatchMessage(msg);//这一句最关键,Message的Target是什么?没错,是Handler,下面我们就来看一下Handler类                if (logging != null) {                    long wallTime = SystemClock.currentTimeMicro() - wallStart;                    long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;                    logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);                    if (logging instanceof Profiler) {                        ((Profiler) logging).profile(msg, wallStart, wallTime,                                threadStart, threadTime);                    }                }                // 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.recycle();//回收利用Message,所以以后我们使用Message的时候,多使用obtain方法。            }        }    }    /**     * Return the Looper object associated with the current thread.  Returns     * null if the calling thread is not associated with a Looper.     */    public static Looper myLooper() {        return sThreadLocal.get();    }        /**     * Return the {@link MessageQueue} object associated with the current     * thread.  This must be called from a thread running a Looper, or a     * NullPointerException will be thrown.     */    public static MessageQueue myQueue() {        return myLooper().mQueue;    }    private Looper() {        mQueue = new MessageQueue();        mRun = true;        mThread = Thread.currentThread();    }    public void quit() {        Message msg = Message.obtain();        // NOTE: By enqueueing directly into the message queue, the        // message is left with a null target.  This is how we know it is        // a quit message.        mQueue.enqueueMessage(msg, 0);    }}

我们来看一下Handler类的源代码

/* * Copyright (C) 2006 The Android Open Source Project */package android.os;import android.util.Log;import android.util.Printer;import java.lang.reflect.Modifier;/** * A Handler allows you to send and process {@link Message} and Runnable * objects associated with a thread's {@link MessageQueue}.  Each Handler * instance is associated with a single thread and that thread's message * queue.  When you create a new Handler, it is bound to the thread  * message queue of the thread that is creating it -- from that point on, * it will deliver messages and runnables to that message queue and execute * them as they come out of the message queue. * /public class Handler {    private static final boolean FIND_POTENTIAL_LEAKS = false;    private static final String TAG = "Handler";    /**     * Callback interface you can use when instantiating a Handler to avoid     * having to implement your own subclass of Handler.     */    public interface Callback {        public boolean handleMessage(Message msg);    }        /**     * Subclasses must implement this to receive messages.     */    public void handleMessage(Message msg) {    }        /**     * Handle system messages here.     */    public void dispatchMessage(Message msg) {//重要,在Lopper.loop()方法里面里调用的就是这个方法        if (msg.callback != null) {            handleCallback(msg);//msg的callBack成员变量是Runnable类型,这里执行的是msg.callback.run(),但是我们一般不给Message的callback成员变量赋值。        } else {            if (mCallback != null) {//如果我们给new()的Handler类的Callback类型的成员变量赋值,就往下面执行,但是我们一般不这么做。                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);//我们一般在这做我们想要的操作,这个方法需要我们继承Handler类后重写。        }    }    /**     * Default constructor associates this handler with the queue for the     * current thread.     *     * If there isn't one, this handler won't be able to receive messages.     */    public Handler() {        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());            }        }        mLooper = Looper.myLooper();        if (mLooper == null) {            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        }        mQueue = mLooper.mQueue;        mCallback = null;    }    /**     * Constructor associates this handler with the queue for the     * current thread and takes a callback interface in which you can handle     * messages.     */    public Handler(Callback callback) {        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());            }        }        mLooper = Looper.myLooper();        if (mLooper == null) {            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        }        mQueue = mLooper.mQueue;        mCallback = callback;    }    public final Message obtainMessage()    {        return Message.obtain(this);//获取msg,最后调用的msg的obtain()方法,最后msg的target就是this,也就是调用者Handler    }     /**     * Use the provided queue instead of the default one.     */    public Handler(Looper looper) {//MessageQueue怎么关联起来,其实就是在这里关联起来的,通过Handler的构造方法。        mLooper = looper;        mQueue = looper.mQueue;        mCallback = null;    }    /**     * Use the provided queue instead of the default one and take a callback     * interface in which to handle messages.     */    public Handler(Looper looper, Callback callback) {        mLooper = looper;        mQueue = looper.mQueue;        mCallback = callback;    }    // if we can get rid of this method, the handler need not remember its loop    // we could instead export a getMessageQueue() method...     public final Looper getLooper() {        return mLooper;    }    private final void handleCallback(Message message) {        message.callback.run();    }    final MessageQueue mQueue;    final Looper mLooper;    final Callback mCallback;    IMessenger mMessenger;}

Looper类和Handler类的源代码不完整,只是分析了和HandlerThread相关的成员变量和方法。

经过我们的一步步分析,现在思路就清晰了:

1. 当HandlerThread运行到Looper.loop()的时候,一直死循环。通过msg.target.dispatchMessage(msg)方法让msg的target(当通过Handler的obtainMessage()系列方法获取msg的时候,msg的target就是该handler)也就是Handler去通过它的handleMessage(msg)方法去处理msg。

2. 但是msg是那里来的?通过看源代码我们发现是通过当前线程的Looper的MessageQueue类型的变量mQueue.next()方法得到的。

3. Handler也有一个MessageQueue类型的变量,那么,Handler的MessageQueue变量怎么和Looper类的MessageQueue类型变量有关系吗?

4. 记不记得Handler类有一个构造方法叫public Handler(Looper) ? 对了,就是这个构造方法让他们产生了关系。( HandlerThread有一个Looper类型的变量,通过getLooper()方法能获取,传入到Handler类的构造方法,这样,Handler就和HandlerThread联系起来了)。

5. 以至于最后HandlerThread操作的是和Handler同一个MessageQueue。

6. Handler可以通过sendMessage(msg)系列方法把msg放到MessageQueue,然后HandlerThread把msg从MessageQueue里面取出来,然后调用Handler的handleMessage(msg)方法处理。

通俗的总结一下运行时的流程:Handler把Message放到MessageQueue,HandlerThread不停的从MessageQueue里拿出来Message,然后调用Handler的HandleMessage(Message)方法不停的处理Message。

经过分析,我们来写一个demo测试一下,有消息队列的线程(非主线程):

工程如下

HandlerThread分析Demo

下面是我测试结果:


结果表示:HandlerThread确实维护了一个消息队列,从Log中可以看出他们的TID都是一样的。

总结:

1. HandlerThread维护了一个消息队列,这样我们不用到处新建对象。

2. Message其实有一套缓冲+循环利用机制,以后用到Message的地方都用obtain()系列方法获取,能节约资源,提高效率。

原创粉丝点击