Android异步操作之HandlerThread

作者: BlainPeng | 来源:发表于2016-05-07 17:03 被阅读563次

    HandlerThread是什么?

    HandlerThread继承了Thread,它是一种可以使用HandlerThread。它和普通的Thread有显著的不同之处:普通Thread主要用于在run方法中执行一个耗时任务,而HandlerThread在内部创建了消息队列,外界需要通过Handler的消息方式来通知HandlerThread执行一个具体的任务。

    在子线程创建Handler

    上篇文章分析了Handler+Thread异步操作的原理,但是我们创建的Handler都是在主线程,那么可不可以在子线程也来创建一个Handler了?

    new Thread(){
            @Override
            public void run() {
                Looper.prepare();
                Handler handler = new Handler(Looper.myLooper());
                Looper.loop();
            }
        }.start();
    

    可是可以,但这样是不是觉得有点麻烦了?
    不过Android已经帮我们封装好了,那就是我们今天的主角:HandlerThread

    HanlderThread基本用法

        public class MainActivity extends AppCompatActivity {
    
        private HandlerThread mThread;
        private Handler mThreadHandler;
        private MyRunnable mRunnable;
        private MyRunnable mRunnable2;
        private TextView mText;
        private TextView mTextTwo;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mText = (TextView) findViewById(R.id.tv_text);
            mTextTwo = (TextView) findViewById(R.id.tv_text2);
            
            mThread = new HandlerThread("MainActivity");
            //HandlerThread本质还是线程,所以必须start起来
            mThread.start();
            //将线程与HandlerThread绑定在一起
            mThreadHandler = new Handler(mThread.getLooper());
    
        }
    
        public void begin(View view) {
            mRunnable = new MyRunnable(this, 1);
            mRunnable2 = new MyRunnable(this, 2);
            mThreadHandler.post(mRunnable);
            mThreadHandler.post(mRunnable2);
    
        }
    
        private static class MyRunnable implements Runnable {
    
            private final WeakReference<MainActivity> mActivity;
            private int mOrder;
    
            public MyRunnable(MainActivity mainActivity, int order) {
                this.mActivity = new WeakReference<>(mainActivity);
                this.mOrder = order;
            }
    
            @Override
            public void run() {
                final MainActivity activity = mActivity.get();
                //模拟耗时操作
                SystemClock.sleep(3000);
    
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
    
                        if (mOrder == 1) {
                            activity.mText.setText("我是任务一");
                        } else {
                            activity.mTextTwo.setText("我是任务二");
                        }
                    }
                });
    
    
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            mThreadHandler.removeCallbacks(mRunnable);
            mThreadHandler.removeCallbacks(mRunnable2);
            //终止线程  
            mThread.quit();//还可以使用mThread.quitSafely();
        }
    }
    
    HandlerThread.gif

    Demo非常简单,就是通过handler提交两个耗时任务给HandlerThread,从效果图来看,很显然耗时任务是按顺序执行的。所以,HandlerThread适用于单线程+异步队列模型场景

    源码分析

    我们在demo中创建HandlerThread的实例对象并启动了该线程,看看源码如何实现的:

    public class HandlerThread extends Thread {
        int mPriority;
        int mTid = -1;
        Looper mLooper;
    
        public HandlerThread(String name) {
            super(name);
            mPriority = Process.THREAD_PRIORITY_DEFAULT;
        }
    
        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;
    }
    

    是不是和我们在上文提到的自己在子线程创建Handler的代码相似,是的。不过它给HandlerThread设置了优先级(Priority)

    线程优先级

    新创建的线程的优先级默认和创建它的母线程保持一致,为了不让新创建的工作线程和UI线程抢占CPU资源,我们可以见降低工作线程的优先级。Android系统提供了一些优先级值:

    HREAD_PRIORITY_DEFAULT,值为0
    THREAD_PRIORITY_LOWEST,值为19
    THREAD_PRIORITY_BACKGROUND 值为10
    THREAD_PRIORITY_MORE_FAVORABLE 值为-1
    THREAD_PRIORITY_LESS_FAVORABLE 值为1
    

    线程的优先级的取值范围为-20到19。值越小,优先级越高,而优先级高的获得的CPU资源更多,反之则越少。而源码中给HandlerThread设置的优先级值为:Process.THREAD_PRIORITY_DEFAULT。即然我们的HandlerThread是用来处理后台任务的,我们可以将其优先级值设为:THREAD_PRIORITY_BACKGROUND,可以用通过它的构造方法来设置

    mThread = new HandlerThread("MainActivity",Process.THREAD_PRIORITY_BACKGROUND);
    

    注意

    HandlerThread绑定的Handler属于子线程,是不能直接更新UI的,我们可以通过runOnUiThread(Runnable r)来进行线程的切换。

    相关文章

      网友评论

        本文标题:Android异步操作之HandlerThread

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