转载请注明出处:
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

更多相关文章

  1. 低版本android project在高版本ADK中运行方法
  2. Android中应用界面主题Theme使用方法和页面定时跳转应用
  3. G1安装android软件方法 (实机运行)
  4. android设置主题和自定义主题的方法
  5. android intent使用方法
  6. Android webkit webkit中skia的使用方法简析
  7. android(java)对网络状态(socket)判断的方法
  8. 安装Android Studio遇到中文乱码的解决方法

随机推荐

  1. java个推实战,Android和Ios
  2. Android(安卓)为什么主线程的looper 一直
  3. MacAndroid源码下载 Android10详解
  4. 一起Talk Android吧(第二百六十五回:Androi
  5. Android中Activity, View,Window,DecorVi
  6. Android(安卓)Socket与HTTPS校验
  7. 超新鲜的字节客户端Android面经,附面试题
  8. 2015年11月广师android群内容分享
  9. Android手机分辨率问题
  10. 在android上向nodejs中添加第三方node模