从HandlerThread 的使用来分析HandlerThread的源码

转载请注明出处:
http://blog.csdn.net/yianemail/article/details/51839509

一:前言

再分析HandlerThread 的使用之前,我们先来简要介绍一下在android中线程的几种表现形式。
线程在android 中是很重要的概念,由于android的uiThread特性,我们常常要利用子线程进行耗时操作。uiThread进行界面的更新处理。在android 中,出了最为常见的Thread之外,还有AsyncTask,IntentService 以及要介绍的HandlerThread。

上述几种虽然都是android 中概念意义上的线程,但是它们具有不同的特性以及不同的使用场景。

  • AsyncTask 我们在前文已经介绍,底层封装了线程池以及利用Handler更新ui
  • IntentService内部则使用了HandlerThread
  • HandlerThread 则是Thread以及looper的封装
二:HandlerThread实例

为了表现HandlerThread 与传统的使用new thread () 的使用区别,我们分别写两个demo来加以区分。

1,通过使用new thread () 形式更新ui

看下activity代码

public class NewThreadUiActivity extends AppCompatActivity {
    private static final int MESSAGE_UI_HANDLER = 0X11;
    private static final int MESSAGE_THREAD_HANDLER = 0X12;
    private Looper threadLooper;
    private TextView textView;
    /**
     * 此handler 是UI线程的Handler
     */
    Handler uiHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MESSAGE_UI_HANDLER:
                    textView.setText("执行更新");
                    break;
            }
        }
    };


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.messgae_tv);
        /**
         * 子线程模拟耗时任务
         */
        new ThreadLooper().start();
    }

    class ThreadLooper extends Thread {
        @Override
        public void run() {
            super.run();
            Looper.prepare();
            threadLooper = Looper.myLooper();
            /**
             * 子线程的Handler
             */
            Handler threadHandler = new Handler(threadLooper) {
                @Override
                public void handleMessage(Message message) {
                    super.handleMessage(message);

                    switch (message.what) {

                        case MESSAGE_THREAD_HANDLER:
                            uiHandler.sendEmptyMessageDelayed(MESSAGE_UI_HANDLER, 1000);
                            break;
                    }
                }
            };

            threadHandler.sendEmptyMessageDelayed(MESSAGE_THREAD_HANDLER, 1000);

            Looper.loop();
        }
    }
}

主界面很简单,就只有一个textview,我们在onCreat()中通过执行匿名线程 。执行逻辑可能有点绕,我们看到在程序中我们实例化了uiHandler 以及threadHandler 两个handler ,其中uiHandler 用来更新界面,threadHandler 用来作为一个过渡,往uiHandler发送messgae 用来提醒uiHandler 更新界面。
你可能要问了,

“wtf ?! , 明明一个handler 就可以,你为毛弄两个?“

咳咳,这位大哥,你忘了我们本文要介绍的主题了么,HandlerThread是封装了thread 以及looper ,(注意该looper 是子线程的looper)。既然有looper 我们自然开启looper.loop() ;这样才能为后来的HandlerThread 的使用做出来更加鲜明的对比。
看下执行结果,

这里写图片描述

2,通过使用Handlerthread 形式更新ui
public class NewThreadUiActivity extends AppCompatActivity {
    private static final int MESSAGE_UI_HANDLER = 0X11;
    private static final int MESSAGE_THREAD_HANDLER = 0X12;
    private Looper threadLooper;
    private TextView textView;
    /**
     * 此handler 是UI线程的Handler
     */
    Handler uiHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MESSAGE_UI_HANDLER:
                    textView.setText("执行更新");
                    break;
            }
        }
    };


    @Override
    protected void onDestroy() {
        super.onDestroy();
        //别忘了在onDestroy 退出

        handlerThread.quit();
    }
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.messgae_tv);

        HandlerThread handlerThread=new HandlerThread("handlerthread");
        handlerThread.start();

        Handler threadHandler=new Handler(handlerThread.getLooper());
        uiHandler.sendEmptyMessageDelayed(MESSAGE_UI_HANDLER, 1000);

    }

}

可以看到,采用HandlerThread 的方式为我们省去了new Thread() 以及looper.prepare()等一些列方法。获得了跟new Thread()的方式相同的效果。

三:HandlerThread源码分析

首先看HandlerThread 的实现方式

HandlerThread handlerThread = new HandlerThread("handlerthread");

 handlerThread.start();

看下构造函数

/**
 * 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.
 */
...

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

其实看下它的注释就能明白大概意思,“开启一个带有looper的新的线程….请注意一定要调用start() 方法“

在构造函数中,设置了一下他的默认优先级

通过源码我们可知,HandlerThread 是Thread的子类,
再来分析一下start() 方法,(也就是run)

  @Override
    public void run() {
     //获得当前线程的id
        mTid = Process.myTid();
         //实例化message QUEUE等,
        Looper.prepare();
        //持有锁机制来获得当前线程的Looper对象
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        //该方法实现体是空的,子类可以实现该方法,作用就是在线程循环之前做一些准备工作,
        onLooperPrepared();
         //启动loop 循环
        Looper.loop();
        mTid = -1;
    }

以上代码中的注释已经写得很清楚了,以上run方法主要作用就是调用了Looper.prepare和Looper.loop构建了一个循环线程。

其实本质还是handler 的一套机制。

四:总结:

1.HandlerThread适用于构建循环线程。

2.在创建Handler作为HandlerThread线程消息执行者的时候必须调用start方法之后,因为创建Handler需要的Looper参数是从HandlerThread类中获得,而Looper对象的赋值又是在HandlerThread的run方法中创建。

源码下载:https://github.com/outparadox/HandlerThread

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值