前言
当我们需要在子线程创建Handler时,可能需要这样处理:(关于Handler机制可以移步Handler消息通信机制,原来如此简单)
...
private static class ChildTread extends Thread {
public Handler mThreadHandle;
@Override
public void run() {
super.run();
//初始化Looper
Looper.prepare();
//创建Handler
mThreadHandle = new Handler(Looper.myLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//在子线程的Handler发送消息给UIHandler
mThreadHandle.sendEmptyMessage(1);
}
};
//开启Looper循环
Looper.loop();
}
}
...
//启动线程
ChildTread childTread = new ChildTread();
childTread.start();
这样我们可以在在子线程中创建Handler,如果在多个子线程中创建Handler,需要重复编写以上代码。这样感觉太蛋疼了,代码太冗余了。还有可出现阻塞UI线程。有人想自己可以封装下。其实Android已经给我们提供HandlerThread,帮我们完成以上内容。
一、HandlerThread使用
HandlerThread是一条内部带有Looper的线程。如何使用HandlerThread?
....
//创建HandlerThread实例
HandlerThread mHandlerThread = new HandlerThread("handlerThread");
/启动线程
mHandlerThread.start();
Handler handler = new Handler(mHandlerThread.getLooper()) {
//运行在HandlerThread线程中
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//进行消息处理(可耗时操作)
...
}
};
//在主线程发送消息
handler.sendEmptyMessage(1);
new Thread(() -> {
//在子线程中发送消息
handler.sendEmptyMessage(2);
}).start();
....
二、HandlerThread源码解析
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable
Handler mHandler;
//设置线程名
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
/**
* Constructs a HandlerThread.
*
* @param name
* @param priority The priority to run the thread at. The value supplied must be from
* {@link android.os.Process} and not from java.lang.Thread.
* 可以指定线程的优先级
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
/**
* 子类需要重写该方法,在Looper循环前做一些初始化的事
*/
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
//创建Looper
Looper.prepare();
//加同步锁,用于线程间通信
synchronized (this) {
//获取Looper
mLooper = Looper.myLooper();
//Looper已经创建,唤醒阻塞在获取Looper的线程
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
//开始循环
Looper.loop();
mTid = -1;
}
/**
* 获取当前线程的 Looper
*
* @return The looper.
*/
public Looper getLooper() {
//如果线程不是存活状态,就返回 null
if (!isAlive()) {
return null;
}
//如果线程启动后,Looper 还没创建,就 wait() 等待 ,创建 Looper 后 notify唤醒
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
/**
* @return a shared {@link Handler} associated with this thread
* @hide
*/
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
/**
* 退出循环
*/
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;
}
/**
* Returns the identifier of this thread. See Process.myTid().
*/
public int getThreadId() {
return mTid;
}
}
- 调用getLooper( )时会判断线程是否存活,Looper是否初始化,如何还没创建Looper会wait等待。
- 在run( )方法中创建Looper,并开启Looper循环。可以重写onLooperPrepared( )进行初始化工作。
- 可以设置HandlerThread的优先级(android.os.Process)。 默认HandlerThread(优先级数值为5)的优先级低于普通线程(优先级数值为5)。
- HandlerThread拥有自己的消息队列,不会阻塞UI线程。里面的消息任务是串行执行。
三、总结
HandlerThread是内部拥有Looper和Handler的线程,不会阻塞UI线程。对于IO网络操作,不适合使用HandlerThread。
网友评论