美文网首页
HandlerThread了解吗?

HandlerThread了解吗?

作者: Dora_Liang | 来源:发表于2018-12-21 21:49 被阅读87次

    前言

    当我们需要在子线程创建Handler时,可能需要这样处理:(关于Handler机制可以移步Handler消息通信机制,原来如此简单

     ...
     private static class ChildTread extends Thread {
            public Handler mThreadHandle;
    
            @Override
            public void run() {
                super.run();
                //初始化Looper
                Looper.prepare();
                //创建Handler
                mThreadHandle = new Handler(Looper.myLooper()) {
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        //在子线程的Handler发送消息给UIHandler
                        mThreadHandle.sendEmptyMessage(1);
                    }
                };
                //开启Looper循环
                Looper.loop();
            }
        }
      ...
    
    //启动线程
     ChildTread childTread = new ChildTread();
     childTread.start();
    

    这样我们可以在在子线程中创建Handler,如果在多个子线程中创建Handler,需要重复编写以上代码。这样感觉太蛋疼了,代码太冗余了。还有可出现阻塞UI线程。有人想自己可以封装下。其实Android已经给我们提供HandlerThread,帮我们完成以上内容。

    一、HandlerThread使用

    HandlerThread是一条内部带有Looper的线程。如何使用HandlerThread?

    ....
    //创建HandlerThread实例
    HandlerThread mHandlerThread = new HandlerThread("handlerThread");
    /启动线程
    mHandlerThread.start();
    
    Handler handler = new Handler(mHandlerThread.getLooper()) {
       //运行在HandlerThread线程中
       @Override
       public void handleMessage(Message msg) {
             super.handleMessage(msg);
              //进行消息处理(可耗时操作)
              ...
             }
        };
        //在主线程发送消息
        handler.sendEmptyMessage(1);
        new Thread(() -> {
           //在子线程中发送消息
           handler.sendEmptyMessage(2);
        }).start();
    ....
    

    二、HandlerThread源码解析

    public class HandlerThread extends Thread {
        int mPriority;
        int mTid = -1;
        Looper mLooper;
        private @Nullable
        Handler mHandler;
    
        //设置线程名
        public HandlerThread(String name) {
            super(name);
            mPriority = Process.THREAD_PRIORITY_DEFAULT;
        }
    
        /**
         * Constructs a HandlerThread.
         *
         * @param name
         * @param priority The priority to run the thread at. The value supplied must be from
         *                 {@link android.os.Process} and not from java.lang.Thread.
         *                 可以指定线程的优先级
         */
        public HandlerThread(String name, int priority) {
            super(name);
            mPriority = priority;
        }
    
        /**
         * 子类需要重写该方法,在Looper循环前做一些初始化的事
         */
        protected void onLooperPrepared() {
        }
    
        @Override
        public void run() {
            mTid = Process.myTid();
            //创建Looper
            Looper.prepare();
            //加同步锁,用于线程间通信
            synchronized (this) {
                //获取Looper
                mLooper = Looper.myLooper();
                //Looper已经创建,唤醒阻塞在获取Looper的线程
                notifyAll();
            }
            Process.setThreadPriority(mPriority);
            onLooperPrepared();
            //开始循环
            Looper.loop();
            mTid = -1;
        }
    
        /**
         * 获取当前线程的 Looper
         *
         * @return The looper.
         */
        public Looper getLooper() {
            //如果线程不是存活状态,就返回 null
            if (!isAlive()) {
                return null;
            }
    
            //如果线程启动后,Looper 还没创建,就 wait() 等待 ,创建 Looper 后 notify唤醒
            synchronized (this) {
                while (isAlive() && mLooper == null) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
            return mLooper;
        }
    
        /**
         * @return a shared {@link Handler} associated with this thread
         * @hide
         */
        @NonNull
        public Handler getThreadHandler() {
            if (mHandler == null) {
                mHandler = new Handler(getLooper());
            }
            return mHandler;
        }
    
        /**
         * 退出循环
         */
        public boolean quit() {
            Looper looper = getLooper();
            if (looper != null) {
                looper.quit();
                return true;
            }
            return false;
        }
    
        /**
         * 安全退出循环(如果还有非延时消息未处理,等处理完,退出)
         */
        public boolean quitSafely() {
            Looper looper = getLooper();
            if (looper != null) {
                looper.quitSafely();
                return true;
            }
            return false;
        }
    
        /**
         * Returns the identifier of this thread. See Process.myTid().
         */
        public int getThreadId() {
            return mTid;
        }
    }
    
    • 调用getLooper( )时会判断线程是否存活,Looper是否初始化,如何还没创建Looper会wait等待。
    • 在run( )方法中创建Looper,并开启Looper循环。可以重写onLooperPrepared( )进行初始化工作。
    • 可以设置HandlerThread的优先级(android.os.Process)。 默认HandlerThread(优先级数值为5)的优先级低于普通线程(优先级数值为5)。
    • HandlerThread拥有自己的消息队列,不会阻塞UI线程。里面的消息任务是串行执行。

    三、总结

    HandlerThread是内部拥有Looper和Handler的线程,不会阻塞UI线程。对于IO网络操作,不适合使用HandlerThread。

    相关文章

      网友评论

          本文标题:HandlerThread了解吗?

          本文链接:https://www.haomeiwen.com/subject/crdilftx.html