一、HandlerThread是什么
HandlerThread(public class HandlerThread extends Thread{})是一个自带Looper的线程,Looper可以用于创建Handler对象。
二、HandlerThread的作用
如下代码所示,在Handler的构造方法中,通过Looper.myLooper()方法,获取当前线程中的Looper对象,如果获取到的Looper对象为null,系统会给我抛出一个Can't create handler inside thread that has not called Looper.prepare()的运行时异常;
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
复制代码
为什么在主线程中我们可以直接创建Handler对象呢
我们可以查看ActivityThread类,在main()方法中执行了 Looper.prepareMainLooper()方法,在prepareMainLooper()方法中,系统为主线程创建了Looper对象,所以在主线程才不会抛出Looper为null不能创建Handler的运行时异常;
如果我们需要使用Handler给子线程发送消息,就需要自己创建Handler,Looper,并调用Looper.loop()方法。HandlerThread正是为这样的使用场景所设计的,把使用细节封装了起来,简化了我们的使用流程。
三、如何使用HandlerThread
HandlerThread handlerThread = new HandlerThread("handler-thread-test");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i("tag", "当前线程名字=" + Thread.currentThread().getName());
//接收来自主线程的消息
if (msg != null && msg.obj != null && msg.obj instanceof String) {
String str = (String) msg.obj;
Log.i("tag", "str:" + str);
try {
//耗时操作
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
//主线程给工作线程发送消息
Message message = handler.obtainMessage();
message.obj = "这是一条来自主线程的消息";
handler.sendMessage(message);
复制代码
执行结果:
注:需要先调用start方法,才能创建Handler。由下代码可见,Looper对象是在run方法中创建的,所以如果不启动线程,获取的Looper对象还是为null;handler.post run方法是在子线程中,因此可以执行一些耗时操作;
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
复制代码
当我们启动了HandlerThread,如果还没有执行run()方法,此时获取Looper对象的方法getLooper()就会一直处于等待状态,直到执行了run方法后,才会唤醒getLooper()方法,并返回Looper对象。同时,如果没有启动线程的话,获取Looper对象,则直接返回null。代码如下:
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,可以调用quit()或quitSafely()结束线程执行。
由于个人能力和水平有限,如有不足之处,希望大家能够给与批评和指正,希望能和大家一起学习,一起进步。