其他分享
首页 > 其他分享> > HandlerThread的使用

HandlerThread的使用

作者:互联网

为了方便在一个新线程中处理消息,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);
        }
    }

标签:target,HandlerThread,Handler,线程,Looper,使用,msg,Message
来源: https://blog.51cto.com/u_15147256/2799143