HandlerThread的使用

来源:互联网 发布:小世界网络的度分布 编辑:程序博客网 时间:2024/06/14 00:20

为了方便在一个新线程中处理消息,android提供了HandlerThread

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.

其使用步骤如下,假设有两个线程,一个主线程A(Handler所在线程),另外一个Looper所在线程B,

1.主线程A中新建一个HandlerThread,然后调用start()启动新线程B

        HandlerThread wmHandlerThread = new HandlerThread("WindowManager");        wmHandlerThread.start();
public class HandlerThread extends Thread {    //新线程B创建的Looper,由于Looper是在static ThreadLocal保存,首先static相当于    //进程中的全局变量,所有线程共享(相同),但是ThreadLocal相当于每个线程有自己独一无二    //的一份Looper(不同),可以利用mLooper = Looper.myLooper()获取    //mLooper非private,线程A可以获取    Looper mLooper;    public void run() {        mTid = Process.myTid();        Looper.prepare();        synchronized (this) {            mLooper = Looper.myLooper();            notifyAll();        }        Process.setThreadPriority(mPriority);        onLooperPrepared();        //新线程B开始循环        Looper.loop();        mTid = -1;    }}

2.主线程A新建一个Handler ,然后可以通过这个Handler组装消息,在线程A中将消息发送到Looper所在的线程B中处理,

//Handler的构造函数可以无参,此时必须保证所在线程Looper已经建立//构造函数还可以输入其他线程的Looper,这样消息会在Looper所在线程处理Handler wmHandler = new Handler(wmHandlerThread.getLooper());
    public Looper getLooper() {        if (!isAlive()) {            return null;        }        // If the thread has been started, wait until the looper has been created.        synchronized (this) {            while (isAlive() && mLooper == null) {                try {                    wait();                } catch (InterruptedException e) {                }            }        }        return mLooper;    }

3.线程A通过Handler发送消息,例如通过Handler.obtainMessage先组装一个Message,

    public final Message obtainMessage(int what, Object obj)    {        return Message.obtain(this, what, obj);    }

其中,消息中的target为本身,即线程A中的wmHandler对象。

    public static Message obtain(Handler h, int what, Object obj) {        Message m = obtain();        //这里的target为线程A中的wmHandler对象        m.target = h;        m.what = what;        m.obj = obj;        return m;    }

在java中,所有实例域、静态域和数组元素保存在堆内存,堆内存在线程之间共享,所以在Looper所在线程B中依然可以访问m.target,即wmHandler,相当于在Looper所在线程B利用线程A中提供的方法去处理消息,实际的处理过程是在线程B中。

4.Looper处理消息

  public static void 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;        // 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();        for (;;) {            Message msg = queue.next(); // might block            if (msg == null) {                // No message indicates that the message queue is quitting.                return;            }            // 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);            }            //循环处理消息            msg.target.dispatchMessage(msg);            if (logging != null) {                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);            }            // 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();        }    }

其中,最主要的就是msg.target.dispatchMessage(msg),获取msg中的target,也就是线程A中的wmHandler对象的dispatchMessage函数。从dispatchMessage函数可以看出,可以通过以下三种方法处理消息:
如果定义了msg的callback,会去利用msg.callback处理Message;
如果在构造Handler时,定义了mCallback,会去利用mCallback.handleMessage处理Message;
否则通过继承Handler,重写handleMessage函数去处理Message,一般这个方法最普遍。

    public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);        }    }
0 0