• HanderThread基本


    Looper是Handler运行的重要组成部分,UI线程系统自动创建了Looper并提供了自动的启动和停止工作,但普通线程则需要手动创建,而HandlerThread就是系统提供的一种创建带有Looper的Thread的方案,比起Thread+Handler更加灵活和安全。

    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.
       HandlerThread是带有Looper的Thread,在创建Handler时在构造器中使用handlerThread.getLooper()获取这个线程的looper给handler实例,就可以使用这个线程处理handler发送的消息了
     */
    public class HandlerThread extends Thread {
        int mPriority;
        int mTid = -1;
        Looper mLooper;
    
        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;
        }
        
        /**
         * Call back method that can be explicitly overridden if needed to execute some
         * setup before Looper loops.
         */
        protected void onLooperPrepared() {
        }
    
        @Override
        public void run() {
            mTid = Process.myTid();
            Looper.prepare();
            synchronized (this) {
                mLooper = Looper.myLooper();
                notifyAll();
            }
            Process.setThreadPriority(mPriority);
            onLooperPrepared();
            Looper.loop();
            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()) {
                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;
        }
    
        /**
         * Quits the handler thread's looper.
         * <p>
         * Causes the handler thread's looper to terminate without processing any
         * more messages in the message queue.
         * </p><p>
         * Any attempt to post messages to the queue after the looper is asked to quit will fail.
         * For example, the {@link Handler#sendMessage(Message)} method will return false.
         * </p><p class="note">
         * Using this method may be unsafe because some messages may not be delivered
         * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure
         * that all pending work is completed in an orderly manner.
         * </p>
         *
         * @return True if the looper looper has been asked to quit or false if the
         * thread had not yet started running.
         *
         * @see #quitSafely
         * 线程的looper直接关闭,message queue不再处理和接受消息
         */
        public boolean quit() {
            Looper looper = getLooper();
            if (looper != null) {
                looper.quit();
                return true;
            }
            return false;
        }
    
        /**
         * Quits the handler thread's looper safely.
         * <p>
         * Causes the handler thread's looper to terminate as soon as all remaining messages
         * in the message queue that are already due to be delivered have been handled.
         * Pending delayed messages with due times in the future will not be delivered.
         * </p><p>
         * Any attempt to post messages to the queue after the looper is asked to quit will fail.
         * For example, the {@link Handler#sendMessage(Message)} method will return false.
         * </p><p>
         * 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.
         * </p>
         *
         * @return True if the looper looper has been asked to quit or false if the
         * thread had not yet started running.
         * 线程的looper会等到已在消息队列中的消息被取出后关闭,延时消息不再 
         * 处理,不再接受任何消息
         */
        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;
        }
    }
    
    HandlerThread源码分析

    使用HandlerThread的简单代码

    public class MainActivity extends AppCompatActivity {
    
        private HandlerThread mHandlerThread;
        private Handler mThreadHandler;
    
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            ...
            initThread();
        }
    
    
        private void initThread()
        {
            mHandlerThread = new HandlerThread("thread-name");
            mHandlerThread.start();
    
            mThreadHandler = new Handler(mHandlerThread.getLooper())
            {
                @Override
                public void handleMessage(Message msg)
                {
                    update();
                }
            };
    
        }
    
        private void update()
        {
            try
            {
                //模拟耗时
                Thread.sleep(2000);
                //完成后通知主线程
                主线程Handler.post()/sendXXMessage()
    
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
    
        }
    
        @Override
        protected void onResume()
        {
            super.onResume();
            //发送消息给该子线程,让其处理一段任务
            mThreadHandler.sendEmptyMessage("some-message");
        }
    
        @Override
        protected void onDestroy()
        {
            super.onDestroy();
            //不用该线程时需要手动停止Looper
            mHandlerThread.quitSafely();
        }
    }

    总结

    HandlerThread就是内部建立了looper工作机制的Thread。

    用处

    1.在UI线程中,无论是更新UI,还是执行其他异步任务,都会用到MainLooper,为了降低MainLooper的负载,提高UI线程的性能,就出现了拥有looper的子线程。因为拥有自己的消息队列,他也不会干扰或阻塞主线程。

    2.用于线程间通信,比如一个子线程发送消息到另一个子线程处理。

    注意

    1.HandlerThread是一个线程,当处理消息时,也是一个一个拿出来顺序处理的,所以如果一个消息处理较为耗时,下一个消息也只能一直等待,所以需要注意这种后续任务的等待是否会影响到性能。

    2.关闭线程只需要结束run()方法,所以需要接束在run()中死循环的loop()方法,故需要条用quit()或quitSafely()。

  • 相关阅读:
    Wannafly Camp 2020 Day 2D 卡拉巴什的字符串
    [POI2010] GIL-Guilds
    Wannafly Camp 2020 Day 1D 生成树
    [AH2017/HNOI2017] 影魔
    机器学习之决策树
    终端多窗口分屏Terminator
    python的面对对象
    安装 Google BBR 加速VPS网络
    DNSLOG在渗透测试中的玩法儿
    如何利用GitHub搜索敏感信息
  • 原文地址:https://www.cnblogs.com/chitanta/p/9724500.html
Copyright © 2020-2023  润新知