HandlerThread详解

1 HandlerThread基本原理

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

 public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -;
}

  既然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,

 public class CustomHandlerThread extends HandlerThread {
private static final String TAG = "CustomHandlerThread";
private static final int MSG_WHAT = 0x11;
private Handler mResponseHandler;
private Handler mHandler;
private Callback mCallback;
public CustomHandlerThread(Handler responseHandler, Callback callback){
super(TAG);
mHandler = new Handler();
mResponseHandler = responseHandler;
mCallback = callback;
} public void enqueTask(String str, TextView textView){
Log.i(TAG, "receive a str: " + str);
mHandler.obtainMessage(MSG_WHAT, str).sendToTarget();
}
public void prepareHandler(){
mHandler = new Handler(getLooper()){
@Override
public void handleMessage(final Message msg) {
try{
TimeUnit.SECONDS.sleep(2);
final String result = (String)msg.obj;
mResponseHandler.post(new Runnable() {
@Override
public void run() {
mCallback.onResult(result);
}
});
}catch (InterruptedException ie){
ie.printStackTrace();
}
}
};
} public interface Callback{
public void onResult(String result);
}
public void removeMsg(){
mHandler.removeMessages(MSG_WHAT);
} }

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

 public class MainActivity extends Activity implements CustomHandlerThread.Callback{
private TextView mTextView; private CustomHandlerThread mCustomHandlerThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView)findViewById(R.id.textView); mCustomHandlerThread = new CustomHandlerThread(new Handler(), this);
mCustomHandlerThread.start();
mCustomHandlerThread.prepareHandler();
for(int i = 0; i < 10; i++){
mCustomHandlerThread.enqueTask("string"+i);
}
} @Override
public void onResult(String result) {
mTextView.setText(result);
} @Override
protected void onDestroy() {
super.onDestroy();
mCustomHandlerThread.removeMsg();
mCustomHandlerThread.quit();
}
}

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

Android之HandlerThread的更多相关文章

  1. Android 开发 HandlerThread详解 转载

    转载请注明出处:http://blog.csdn.net/vnanyesheshou/article/details/75073307 对于Handler不太懂的可以参考我的这两篇文章: Androi ...

  2. Android开发——HandlerThread以及IntentService详解

    .HandlerThread Android API提供了HandlerThread来创建线程.官网的解释是: //Handy class for starting a new thread that ...

  3. Android中HandlerThread的使用及源代码解析

    关于Hanlder的基本使用能够參见博文<Android中Handler的使用>,假设想了解Handler.Looper.Thread等的相互关系以及内部实现原理能够參见博文<深入源 ...

  4. Android多线程—HandlerThread解析

    一.HandlerThread作用 1.实现多线程:在工作线程之后执行任务(比如一些耗时任务) 2.异步通信.消息传递:实现工作线程与主线程(UI线程)之间的通信,即将工作线程的执行结果传递给主线程, ...

  5. Android(八) HandlerThread

    1.Looper Looper used to run a message loop for a thread. Threads by default do not have a message lo ...

  6. Android HandlerThread 总结使用

    转载请标明出处:http://www.cnblogs.com/zhaoyanjun/p/6062880.html 本文出自[赵彦军的博客] 前言 以前我在 [Android Handler.Loop ...

  7. Android HandlerThread 的使用及其Demo (转)

    转自http://www.cnblogs.com/hnrainll/p/3597246.html 介绍 首先我们来看看为什么我们要使用HandlerThread?在我们的应用程序当中为了实现同时完成多 ...

  8. 【Android】用HandlerThread模拟AsyncTask功能(ThreadTask)

    前言 AsyncTask是个好东西,能处理绝大多数应用线程和更新UI的任务,由于其内部使用了静态线程池,如果你有一堆异步任务(例如全局定时更新数据.同一个Activity中多个AsyncTask同时执 ...

  9. Android HandlerThread 的使用及其Demo

    今天我们一起来学习下一个Android中比较简单的类HandlerThread,虽然它的初始化有点小麻烦. 介绍 首先我们来看看为什么我们要使用HandlerThread?在我们的应用程序当中为了实现 ...

随机推荐

  1. java web项目基础

      listener,filter,servlet的初始化顺序 web.xml中可以配置如下信息: context-param,listener,filter,servlet. 他们的加载顺序和在we ...

  2. C# IE代理操作

    public class IPProxy { [System.Runtime.InteropServices.DllImport("wininet.dll", SetLastErr ...

  3. Lync Server 2013中央管理存储:自动收集配置数据失败

    Lync Server 2013在安装本地配置存储到配置中央管理存储的本地副本时候提示错如信息:自动收集配置数据失败. 打开Lync Shell,输入Get-CsConfigurationStoreL ...

  4. 使用upstream和subrequest访问第三方服务

    本文是对陶辉<深入理解Nginx>第5章内容的梳理以及实现,代码和注释基本出自此书. 一.upstream:以向nginx服务器的请求转化为向google服务器的搜索请求为例 (一)模块框 ...

  5. openssh6.7.deb download packed for debian7/ubuntu12.04 amd64

    openssh the openssh-server on debian7/ubuntu12.04 is too old and out of date. so now we replace and ...

  6. Arduino 各种模块篇 震动模块 vibrator

    vibrator is a good thing. it has multi-funtionality . :) Now the  vibrator we choose is the one whic ...

  7. 关于《数据格式修改》的简单应用程序(C语言)

    关于<数据格式修改>的简单应用程序(C语言) 至亲爱的博友: 大家好,好久不见了.由于博主还是一名大学在校生,不可避免的需要和指导教师共同完成一些项目,因此前一段时间暂时停止了博客的更新. ...

  8. Android开发之Ubuntu上Eclipse不显示手机设备

    一.准备工作   A.开启Android设备,用USB数据线连接到Ubuntu系统.   B.启用设备的USB调试模试    C.启动Eclipse,在Devices栏会现一个有很多???号的不明设备 ...

  9. 把python文件编译成exe文件

    我用的是py2exe. 下载地址http://sourceforge.net/projects/py2exe/files/py2exe/0.6.9/ 你可以根绝自己的Python版本选择适当的下载 我 ...

  10. C语言之分支结构 if(二)

    If的第三种和第四种形式(tips:也是比较常用的形式) 3).if语句第三种形式: 简单来说就是任意的if或者else里面还可以嵌套任意的if-else语句 语法: if(表达式){ if(表达式2 ...