结构
继承关系
public classHandleThread extends Thread
java.lang.Object
java.lang.Thread
android.os.HandlerThread
类概述
用于方便的创建一个含有looper的线程类。looper用来创建handler类。请注意,仍然需要调用start()方法。
构造函数
public HandlerThread (String name)
构造一个HandlerThread
public HandlerThread (String name, int priority)
构造一个HandlerThread
参数
priority 运行线程的优先级,这个值是由Android.os.Process提供而不是来自java.lang.Thread.
公共方法
public Looper getLooper ()
这个方法返回与此线程相关的Looper。如果该线程不能启动或是由于某种原因isAlive()方法返回false,则这个方法返回null,假如这个线程已经启动,那么此方法将阻塞,直到looper被初始化。
返回值
Looper
public int getThreadId ()
返回线程的标志。详见:Process.myTid()
public boolean quit ()
查看当前运行的looper是否已经退出。假如线程这未启动或者已经结束(即getLooper()方法返回null),这个方法将返回false。否则looper被要求退出并返回true。
public void run ()
调用设置Runnable对象的run()方法。如果没有设置Runnable,什么也不做。
受保护方法
protected void onLooperPrepared ()
如果需要在Looper循环之前执行一些设置,可明确继承该回调方法。
(译者注:如下代码:
mTid = Process.myTid();
Looper.prepare();//创建一个Looper实例,并且存储在ThreadLocal中,ThreadLocal中维护一个HashMap,键是线程号
synchronized (this) {
mLooper = Looper.myLooper();//得到当前线程的Looper,就是刚才perpare方法中创建并存储的那个Looper实例
Process.setThreadPriority(mPriority);
notifyAll();
}
onLooperPrepared();
Looper.loop();//开始轮询
mTid = -1;
)
源码分析:
public class HandlerThread extends Thread{
//线程的优先级
private int mPriority;
//线程的id
private int mTid=-1;
private Looper mLooper;
public HandlerThread(String name){
super(name);
//设置优先级为默认线程
mPriority=Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name,int priority){
super(name);
mPriority=priority;
}
//这个如果有需要的话可以继承重写,例如可以在里面声明个Handler 关联此线程。
protected void onLooperPrepared(){}
//这个很熟悉吧
public void run(){
//得到当前线程的id
mTid=Process.myTid;
//一旦调用这句代码,就在此线程中创建了Looper 对象。这就是为什么我们要在调用线程的start()方法后
//才能得到Looper 对象即 当 调用Looper.myLooper()时不为Null。
Looper.prepare();
//同步代码块,意思就是当获得mLooper对象后,唤醒所有线程。(会在以后的例子中有所体现)
synchronized(this){
mLooper=Looper.myLooper();
notifyAll();
}
//设置线程的优先级
Process.setThreadPriority(mPriority);
//调用上面的方法(需要用户重写)
onLooperPrepared();
//建立了消息循环
Looper.loop();
mTid=-1;
}
public Looper getLooper(){
//线程死了,那就只有NULL了。
if(!isAlive()){
return null;
}
//看见没,又是同步代码块,正好和上面的形成对应,就是说只要线程活着并且我的looper为NULL,那么我就让你一直等。。。
synchronized(this){
while(isAlive()&&mLooper==null){
try{
wait();
}catch(InterruptedException e){}
}
}
return mLooper;
}
public boolean quit(){
Looper looper =getLooper();
if(looper!=null){
//退出消息循环
looper.quit();
return true;
}
return false;
}
//返回线程ID
public int getThreadId(){
return mTid;
}
}
复制代码
整体来说代码还是比较浅显易懂的。主要的作用是建立了一个线程,并且创立了消息队列,有来自己的looper,可以让我们在自己的线程中分发和处理消息。
还有要说明的是handler 与谁相关联不是看声明在什么地方,是看与哪个线程的looper挂钩。默认是主线程的looper.因为主线程中默认就有了looper,消息循环队列。
在android开发中,一说起线程的使用,很多人马上想到new Thread(){...}.start()这种方式。这样使用当然可以,但是多次使用这种方式,会创建多个匿名线程。使得程序运行起来越来越慢。
因此,可以考虑使用一个Handler来启动一个线程,当该线程不再使用就删除,保证线程不会重复创建。
一般会使用Handler handler = new Handler(){...}创建Handler。这样创建的handler是在主线程即UI线程下的Handler,
即这个Handler是与UI线程下的默认Looper绑定的。Looper是用于实现消息队列和消息循环机制的。
因此,如果是默认创建Handler那么如果线程是做一些耗时操作如网络获取数据等操作,这样创建Handler是不行的。
Android API提供了HandlerThread来创建线程。官网的解释是: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.
HandlerThread实际上就一个Thread,只不过它比普通的Thread多了一个Looper。
创建HandlerThread时要把它启动了,即调用start()方法。然后创建Handler时将HandlerThread中的looper对象传入。
HandlerThread thread = new HandlerThread("MyHandlerThread");
thread.start();
mHandler = new Handler(thread.getLooper());
mHandler.post(new Runnable(){...});
那么这个Handler对象就是与HandlerThread这个线程绑定了(这时就不再是与UI线程绑定了,这样它处理耗时操作将不会阻塞UI)。 下面是代码说明:
rivate Handler mHandler;
private HandlerThread mHandlerThread;
private boolean mRunning;
private Button btn;
@Override
protected void onDestroy() {
mRunning = false;
mHandler.removeCallbacks(mRunnable);
super.onDestroy();
}
@Override
protected void onResume() {
mRunning = true;
super.onResume();
}
@Override
protected void onStop() {
mRunning = false;
super.onStop();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(this);
mHandlerThread = new HandlerThread("Test", 5);
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
}
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
while (mRunning) {
Log.d("MainActivity", "test HandlerThread...");
try {
Thread.sleep(200);
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.btn :
mHandler.post(mRunnable);
break;
default :
break;
}
}