概述
HandlerThread继承自Thread类,本质上还是Thread。与普通Thread的区别在于,它在创建一个线程的同时也创建了一个绑定该线程的消息循环,可以在当前线程中分发和处理消息。
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.
官方文档:
https://developer.android.com/reference/android/os/HandlerThread.html
使用
通过下面四步我们可以创建HandlerThread。
创建完成之后就可以开始使用了,调用handler的post()方法,Runnable的run()方法将在子线程中执行。
同样也可以使用Handler发消息的方式。可以在Handler创建时,重写handleMessage()方法。
如果想让HandlerThread退出,可以调用HandlerThread的quit()或quitSafely()。
分析
在子线程的run()方法中,分三步来执行。
1.使用Looper.prepare()创建绑定当前线程的Looper对象;
2.使用上面的Looper对象创建Handler对象;
3.使用Looper.loop()开启消息循环。
关于Message、MessageQueue、Handler、Looper的执行流程,可参考如下链接:
http://blog.csdn.net/ruancoder/article/details/52081614
在HandlerThread类的源码中,采用了同样的方式来创建Looper对象,并赋值给成员变量mLooper。
getLooper()方法返回上面创建的mLooper对象。我们通过调用getLooper()方法,可以获取到mLooper对象去创建Handler。
HandlerThread也可以控制线程的优先级。在HandlerThread类中,有一个成员变量mPriority,该变量在run()方法中通过调用Process.setThreadPriority(mPriority)被使用到。mPriority默认值为THREAD_PRIORITY_DEFAULT,我们也可以在构造方法中传入参数去修改。
注意,mPriority的取值只限于android.os.Process类中的常量,不能取自java.lang.Thread。
如果需要退出消息循环,可以调用quit()或quitSafely()方法。可以看到,方法内部执行的是成员变量mLooper的quit()和quitSafely()方法。在Looper类中,又执行的是MessageQueue的quit(boolean safe)方法。当调用quit()方法时,MessageQueue消息池中所有的消息全部被清空,包括延迟消息和非延迟消息。而调用quitSafely()方法时,只会清空MessageQueue消息池中所有的延迟消息,并将消息池中所有的非延迟消息派发出去让Handler处理。
优点
为什么要使用HandlerThread呢?
1.开发中如果多次使用类似new Thread(){}.start()这种方式开启子线程,会创建多个匿名线程,使得程序运行起来越来越慢,而HandlerThread自带Looper使他可以通过消息机制来多次重复使用当前线程,节省开支。
2.Handler类内部的Looper默认绑定的是UI线程的消息队列,对于非UI线程如果需要使用消息机制,自己去创建Looper较繁琐,由于HandlerThread内部已经自动创建了Looper,直接使用HandlerThread更方便。
HandlerThread继承自Thread类,本质上还是Thread。与普通Thread的区别在于,它在创建一个线程的同时也创建了一个绑定该线程的消息循环,可以在当前线程中分发和处理消息。
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.
官方文档:
https://developer.android.com/reference/android/os/HandlerThread.html
使用
通过下面四步我们可以创建HandlerThread。
// 1.创建HandlerThread对象,并为子线程指定一个名称
HandlerThread handlerThread = new HandlerThread("ruancoder");
// 2.调用start()。此时内部run()方法执行,会创建一个绑定当前线程的Looper对象
handlerThread.start();
// 3.获取HandlerThread的Looper
Looper looper = handlerThread.getLooper();
// 4.使用上面的Looper创建Handler
Handler handler = new Handler(looper);
创建完成之后就可以开始使用了,调用handler的post()方法,Runnable的run()方法将在子线程中执行。
handler.post(new Runnable() {
@Override
public void run() {
// sub thread
}
});
同样也可以使用Handler发消息的方式。可以在Handler创建时,重写handleMessage()方法。
Handler handler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
// sub thread
}
};
然后调用sendMessage()或sendEmptyMessage(),handleMessage()方法将会在子线程中执行。
// 1
handler.sendEmptyMessage(MSG);
// 2
handler.sendMessage(msg);
如果想让HandlerThread退出,可以调用HandlerThread的quit()或quitSafely()。
分析
在介绍HandlerThread之前,先来看一下如果我们需要在子线程中创建Handler该如何实现。
package net.csdn.blog.ruancoder;
public class MainActivity extends Activity {
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new Thread(new Runnable() {
@Override
public void run() {
......
Looper.prepare();// 1
mHandler = new Handler(Looper.myLooper());// 2
Looper.loop();// 3
}
}).start();
}
}
在子线程的run()方法中,分三步来执行。
1.使用Looper.prepare()创建绑定当前线程的Looper对象;
2.使用上面的Looper对象创建Handler对象;
3.使用Looper.loop()开启消息循环。
关于Message、MessageQueue、Handler、Looper的执行流程,可参考如下链接:
http://blog.csdn.net/ruancoder/article/details/52081614
在HandlerThread类的源码中,采用了同样的方式来创建Looper对象,并赋值给成员变量mLooper。
public class HandlerThread extends Thread {
Looper mLooper;
......
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
......
}
getLooper()方法返回上面创建的mLooper对象。我们通过调用getLooper()方法,可以获取到mLooper对象去创建Handler。
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
HandlerThread也可以控制线程的优先级。在HandlerThread类中,有一个成员变量mPriority,该变量在run()方法中通过调用Process.setThreadPriority(mPriority)被使用到。mPriority默认值为THREAD_PRIORITY_DEFAULT,我们也可以在构造方法中传入参数去修改。
注意,mPriority的取值只限于android.os.Process类中的常量,不能取自java.lang.Thread。
int mPriority;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
如果需要退出消息循环,可以调用quit()或quitSafely()方法。可以看到,方法内部执行的是成员变量mLooper的quit()和quitSafely()方法。在Looper类中,又执行的是MessageQueue的quit(boolean safe)方法。当调用quit()方法时,MessageQueue消息池中所有的消息全部被清空,包括延迟消息和非延迟消息。而调用quitSafely()方法时,只会清空MessageQueue消息池中所有的延迟消息,并将消息池中所有的非延迟消息派发出去让Handler处理。
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
优点
为什么要使用HandlerThread呢?
1.开发中如果多次使用类似new Thread(){}.start()这种方式开启子线程,会创建多个匿名线程,使得程序运行起来越来越慢,而HandlerThread自带Looper使他可以通过消息机制来多次重复使用当前线程,节省开支。
2.Handler类内部的Looper默认绑定的是UI线程的消息队列,对于非UI线程如果需要使用消息机制,自己去创建Looper较繁琐,由于HandlerThread内部已经自动创建了Looper,直接使用HandlerThread更方便。