HandlerThread
先看 HandlerThread
的成员变量,源码如下:
public class HandlerThread extends Thread {
// 线程优先级
int mPriority;
// 线程 ID
int mTid = -1;
// 跟线程绑定的 Looper
Looper mLooper;
// 跟线程绑定的 Handler
Handler mHandler;
}
接着,我们看一下 HandlerThread
的构造函数:
// 构造方法,传入线程名称
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
// 构造方法,传入线程名称和线程优先级
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
共有两个构造方法,入参 name
表示线程名称,入参 priority
表示线程的优先级。
接着,有一个模板方法,供扩展用,在 Looper
工作之前会回调,如下:
// 子类覆写,Looper.loop() 之前会回调
protected void onLooperPrepared() {
}
默认是空实现,供子类实现逻辑。
因为 HandlerThread
是 Thread
的子类,所以我们重点看一下 run
方法:
@Override
public void run() {
mTid = Process.myTid();
// 创建 Looper
Looper.prepare();
// 持有锁机制来获得当前线程的Looper对象
synchronized (this) {
mLooper = Looper.myLooper();
// 唤醒,当前线程已经创建mLooper对象成功,这里主要是通知getLooper方法中的wait
notifyAll();
}
// 设置线程的优先级
Process.setThreadPriority(mPriority);
// 这里默认是空方法的实现,我们可以重写这个方法来做一些 Looper工作之前的准备,方便扩展
onLooperPrepared();
// Looper 开始工作
Looper.loop();
mTid = -1;
}
在 Android
系统中,我们执行耗时操作都要另外开启子线程来执行,执行完线程以后线程会自动销毁。所以当我们经常需要异步处理任务时,需要反复开启和销毁线程,非常消耗性能。而 HandlerThread
的工作机制就是 Handler
的工作机制,运行了 run
方法,Looper
就进入死循环,线程也就不会销毁,我们可以通过 HandlerThread
来串行执行多个不同的异步任务。
通过源码可知,HandlerThread
是自带 Looper
的 Thread
,那么怎样获取当前的 Looper
呢?
// 获取当前的 Looper
public Looper getLooper() {
// 线程没有启动或者已经死亡时返回 null
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
// 线程已经启动但是 Looper 对象还没有创建完成
while (isAlive() && mLooper == null) {
try {
// 等待
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
上述分析说到,HandlerThread
开启之后不会自动销毁,那肯定就有主动销毁的方法,如下:
// 退出 Looper 循环,把当前消息队列中的所有消息都抛弃
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
// 退出 Looper 循环,它会让消息队列中的非延迟消息继续得到处理,只抛弃延时消息
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
还有一些其他的方法,如下:
// 获取线程绑定的 Handler
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
// 返回线程ID
public int getThreadId() {
return mTid;
}
HandlerThread
的源码就是这么多,接下来我们看一下 HandlerThread
是怎样使用的。
基本使用方式
步骤一: 创建 HandlerThread 实例
mHandlerThread = new HandlerThread("test");
步骤二: 启动线程
mHandlerThread.start();
步骤三: 创建子线程 Handler
mThreadHandler = new Handler(mHandlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
Log.d("HandlerThreadActivity", Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
mUIHandler.sendMessage(mUIHandler.obtainMessage(1, "success"));
}
}
};
注意:子线程的 Handler
创建时需要用到 HandlerThread
的 Looper
,这样才能保证 Handler
发送的消息在子线程做处理。
步骤四: 销毁线程
mHandlerThread.quit();
完整的使用案例
public class HandlerThreadActivity extends AppCompatActivity implements View.OnClickListener {
TextView mStartThread;
HandlerThread mHandlerThread;
private Handler mThreadHandler;
private UIHandler mUIHandler = new UIHandler(this);
private static class UIHandler extends Handler {
private WeakReference<HandlerThreadActivity> mWeakReference;
public UIHandler(HandlerThreadActivity activity) {
mWeakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
if (mWeakReference.get() != null) {
Log.d("HandlerThreadActivity", Thread.currentThread().getName());
Toast.makeText(mWeakReference.get(), msg.obj.toString(), Toast.LENGTH_SHORT).show();
}
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_thread);
mStartThread = findViewById(R.id.tv_send_message);
mStartThread.setOnClickListener(this);
mHandlerThread = new HandlerThread("test");
mHandlerThread.start();
mThreadHandler = new Handler(mHandlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
Log.d("HandlerThreadActivity", Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
mUIHandler.sendMessage(mUIHandler.obtainMessage(1, "success"));
}
}
};
}
@Override
public void onClick(View v) {
mThreadHandler.sendEmptyMessage(1);
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandlerThread.quit();
}
}
主要是模拟子线程处理耗时操作,案例中在主线程通过子线程的 Handler
发送了一个空消息,子线程通过回调休眠了两秒钟后,通过主线程的 Handler
发送一个成功的消息,最后显示了一个成功的提示。