HandlerThread详解

1 HandlerThread基本原理

  HandlerThread继承自Thread,它是一种可以使用Handler的Thread。它的实现很简单,就是在run方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环。这样,我们就可以直接在HandlerThread中创建Handler了。HandlerThread的run方法如下所示:

 1 public void run() {
 2     mTid = Process.myTid();
 3     Looper.prepare();
 4     synchronized (this) {
 5         mLooper = Looper.myLooper();
 6         notifyAll();
 7     }
 8     Process.setThreadPriority(mPriority);
 9     onLooperPrepared();
10     Looper.loop();
11     mTid = -1;
12 }

  既然HandlerThread中已经有了消息循环,那么我们就可以在HandlerThread类或其子类中直接创建Handler对象,但是我们要记住一点:如果我们需要创建与该HandlerThread线程相关联的Handler的话,我们要使用Handler(Looper looper)构造方法,这样我们所创建的Handler对象才会与当前线程的消息循环相关联。在HandlerThread中,我们可以通过getLooper()方法获得Looper实例。

  从HandlerThread的实现上来看,它和普通Thread有显著不同,普通Thread主要在run方法中执行耗时任务,而HandlerThread在内部创建了消息队列,外界需要通过Handler的消息方式来通知HandlerThread执行一个具体任务。通常,一个普通的Thread线程也可以成为Looper线程,我们只需要为其创建消息队列并开启消息循环即可。看如下实现代码:

class LooperThread extends Thread {public Handler mHandler;public void run() {Looper.prepare();mHandler = new Handler() {public void handleMessage(Message msg) {// process incoming messages here
          }};Looper.loop();}
}

我们可以根据不同应用场景选择不同的实现方式,不过既然Android已经提供了HandlerThread类,那我们在开发过程中可能会更倾向于使用该类完成耗时操作。

2 示例程序

  我们将通过一个简单示例程序来说明HandlerThread的用法。本示例程序中,我们向HandlerThread发送消息,然后HandlerThread返回该消息并显示到TextView上,在这个过程中我们通过sleep来模拟耗时操作。我们将创建一个继承自HandlerThread的类:CustomHandlerThread,

 1 public class CustomHandlerThread extends HandlerThread {
 2     private static final String TAG = "CustomHandlerThread";
 3     private static final int MSG_WHAT = 0x11;
 4     private Handler mResponseHandler;
 5     private Handler mHandler;
 6     private Callback mCallback;
 7     public CustomHandlerThread(Handler responseHandler, Callback callback){
 8         super(TAG);
 9         mHandler = new Handler();
10         mResponseHandler = responseHandler;
11         mCallback = callback;
12     }
13
14     public void enqueTask(String str, TextView textView){
15         Log.i(TAG, "receive a str: " + str);
16         mHandler.obtainMessage(MSG_WHAT, str).sendToTarget();
17     }
18     public void prepareHandler(){
19         mHandler = new Handler(getLooper()){
20             @Override
21             public void handleMessage(final Message msg) {
22                 try{
23                     TimeUnit.SECONDS.sleep(2);
24                     final String result = (String)msg.obj;
25                     mResponseHandler.post(new Runnable() {
26                         @Override
27                         public void run() {
28                             mCallback.onResult(result);
29                         }
30                     });
31                 }catch (InterruptedException ie){
32                     ie.printStackTrace();
33                 }
34             }
35         };
36     }
37
38     public interface Callback{
39         public void onResult(String result);
40     }
41     public void removeMsg(){
42         mHandler.removeMessages(MSG_WHAT);
43     }
44
45 }

  我们先看enqueTask方法,该方法很简单,我们仅用它来接收从外部传来的参数(准确的说是消息内容),并且通过当前线程的Handler将消息发送到当前线程消息队列中,对该消息的处理是在prepareHandler()方法中完成的。在prepareHandler方法中,我们创建Handler实例,并且与当前线程的消息队列相关联,这通过Handler(Looper looper)构造方法完成。mResponseHandler.post方法会将Runnable对象添加到主线程的消息队列,该Runnable对象将会在该mResponseHandler所属的线程中执行,由于mResponseHandler是从主线程传过来的(稍后我们会看到具体实现),因此Runnable将会运行在主线程中。run方法中我们通过回调接口来传递结果。下面我们看下MainActivity中的处理:

 1 public class MainActivity extends Activity implements CustomHandlerThread.Callback{
 2     private TextView mTextView;
 3
 4     private CustomHandlerThread mCustomHandlerThread;
 5     @Override
 6     protected void onCreate(Bundle savedInstanceState) {
 7         super.onCreate(savedInstanceState);
 8         setContentView(R.layout.activity_main);
 9         mTextView = (TextView)findViewById(R.id.textView);
10
11         mCustomHandlerThread = new CustomHandlerThread(new Handler(), this);
12         mCustomHandlerThread.start();
13         mCustomHandlerThread.prepareHandler();
14         for(int i = 0; i < 10; i++){
15             mCustomHandlerThread.enqueTask("string"+i);
16         }
17     }
18
19     @Override
20     public void onResult(String result) {
21         mTextView.setText(result);
22     }
23
24     @Override
25     protected void onDestroy() {
26         super.onDestroy();
27         mCustomHandlerThread.removeMsg();
28         mCustomHandlerThread.quit();
29     }
30 }

上面代码很简单,我们创建CustomHandlerThread并传入Handler对象,该Handler对象是在主线程中创建的,因此与主线程消息队列相关联,创建HandlerThread对象后必须要调用start方法,此外,在调用enqueTask之前必须先调用prepareHandler方法,以免导致空指针异常(Handler还没创建?怎么能向消息队列发送消息呢?)。最后要注意的是,当Activity退出时,我们一定要通过quit方法结束HandlerThread的执行。

转载于:https://www.cnblogs.com/e007/p/6272922.html

Android之HandlerThread相关推荐

  1. Android之HandlerThread源码分析和简单使用(主线程和子线程通信、子线程和子线程通信)

    1.先熟悉handler方式实现主线程和子线程互相通信方式,子线程和子线程的通信方式 如果不熟悉或者忘记了,请参考我的这篇博客     Android之用Handler实现主线程和子线程互相通信以及子 ...

  2. 【Android】HandlerThread详解

    之前总结过Android Handler.Looper.Message.MQ的知识点,我们翻看源码的时候,看到一个关键类HandlerThread,当时还提出过疑问,这个和Thread有什么区别.本节 ...

  3. Android之使用HandlerThread 以及如何退出总结

    1 .使用 HandlerThread handlerThread = new HandlerThread("handlerThread"); handlerThread.star ...

  4. Android中文API(128) —— HandlerThread

    前言 本章内容是android.os.HandlerThread,版本为Android 3.1 r1,翻译来自"雪鹰工作室",再次感谢"雪鹰工作室"!欢迎你一起 ...

  5. Android 多线程之HandlerThread 完全详解

    转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/52426353 出自[zejian的博客] 关联文章: Android ...

  6. java handlerthread_深入Android HandlerThread 使用及其源码完全解析

    本篇我们将来给大家介绍HandlerThread这个类,以前我们在使用线程执行一个耗时任务时总会new一个Thread的线程去跑,当任务执行完后,线程就会自动被销毁掉,如果又由新的任务,我们又得新建线 ...

  7. Android HandlerThread例程

    在多线程通信中我们通常使用handler进行异步通信.在线程中使用handler稍微有一些麻烦,比如说创建handler的时候必须保证当前线程中有Looper对象,否则会创建失败. 安卓的主线程自带一 ...

  8. Android中Handler

    本文通过例子来验证和说明使用Handler对象开启的线程是否和主线程为在同一线程中. 程序结构图如下: [1] HandlerActivity.java中的源码如下: [html] view plai ...

  9. android webview java_Android Webview中调用本地java方法

    在网页调用本地的分享SDK class JsObject { @JavascriptInterface public String toString() { return "injected ...

  10. Android中的Handler

    当我们在处理下载或是其它须要长时间运行的任务时.假设直接把处理函数放在Activity的OnCreate或是OnStart中.会导致运行过程中整个Activity无响应,假设时间过长,程序就会挂掉. ...

最新文章

  1. cv_bridge中的编码模式与实现
  2. GLSL实现滤镜效果
  3. NFV和VNF的现状如何
  4. nginx和php之间是怎样通信的呢(简答)
  5. Jmter操作数据库
  6. php memcache 扩展 libmemcached 安装
  7. 浅谈ES6中的rest参数
  8. DB2 表的常用命令
  9. Android UI学习之SeekBar
  10. 基于ABAQUS蠕变储层稠油蒸汽吞吐开发过程数值模拟
  11. 关于电瓶车管理的思考
  12. snmpwalk与snmpget的区别
  13. cad化工设备绘图_化工CAD制图基础篇,管道布置图学起来
  14. 计算机考研复试C语言常见面试题
  15. 阿里云服务器续费流程方法(图文详解)
  16. 猿来小课Java视频教程讲师浅谈JAVA体系结构
  17. 3DMAX输入序列后消失/闪退问题解决方案
  18. 头歌--CC++函数实训
  19. 液晶屏的Dithering功能
  20. 碧桂园博智林机器人总部大楼_碧桂园的800亿机器人梦,碎了?

热门文章

  1. 解决cdh4.5.0下 MAP任务看不到状态
  2. Eval()、XPath() 和 Bind() 这类数据绑定方法只能在数据绑定控件的上下文中使用
  3. linux那些鲜为人知的小秘密
  4. Mac上设置图片或视频的默认打开软件的方法
  5. Arturia系列合成器插件大合集:Arturia V Collection 8 for mac
  6. 微信小程序 数据绑定
  7. 巧用EasyRecovery监控硬盘 为你的电脑保驾护航
  8. EasyRecovery,拯救那些遗失的文件
  9. Check $M2_HOME environment variable and mvn script
  10. SpringBoot非官方教程 | 第二十二篇: 创建含有多module的springboot工程