在多线程通信中我们通常使用handler进行异步通信。在线程中使用handler稍微有一些麻烦,比如说创建handler的时候必须保证当前线程中有Looper对象,否则会创建失败。
安卓的主线程自带一个Looper,但是我们手动创建的子线程是不会自带Looper对象的,因此我们如果想要在子线程接收信息,也就是在子线程创建handler,就必须在子线程先创建Looper对象,有点麻烦。
于是HandlerThread可以解决这个问题,里面内部自带了Looper对象。
例程
package com.example.handlerthreadtest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "handleTread";
HandlerThread mHandlerThread;
private static final int MSG_UPDATE_INFO = 0x110;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建并启动子线程mHandlerThread
mHandlerThread = new HandlerThread("new thread");
mHandlerThread.start();
//创建一个handler,传入的looper是子线程mHandlerThread的,所以该handler被子线程mHandlerThread持有
Handler workHandler = new Handler(mHandlerThread.getLooper()){
//重写handleMessage方法,在子线程mHandlerThread处理相关操作
@Override
public void handleMessage(Message msg){
super.handleMessage(msg);
Log.d(TAG, "handleMessage: name = " + Thread.currentThread().getName() + ", msg.what = " + msg.what);
}
};
//主线程通过workHandler发送消息给子线程
Log.d(TAG, "sendMessage: name = " + Thread.currentThread().getName());
Message message = new Message();
message.what = 1;
message.obj = "test!";
workHandler.sendMessage(message);
}
@Override
protected void onDestroy(){
super.onDestroy();
mHandlerThread.quit();
}
}
以上例程实现了简单的主线程向子线程发送消息的功能,该子线程就是HandlerThread类型的。
用法
HandlerThread创建的是一个带Looper对象的子线程,通常在该类型的子线程中接收消息(当然也可以发信息),也就是在该类型的子线程中创建handler并重写接收信息的方法。
而对于信息发送方就很简单了,只需要拿到接收方创建的handler就可以直接发信息,并不需要关心接收方是不是HandlerThread还是普通的Thread,因此HandlerThread的用法主要体现在接收方线程上。
1.创建HandlerThread对象
mHandlerThread = new HandlerThread("new thread");
2.启动HandlerThread对象
mHandlerThread.start();
3.创建handler并重写消息接收方法
Handler workHandler = new Handler(mHandlerThread.getLooper()){
//重写handleMessage方法,在子线程mHandlerThread处理相关操作
@Override
public void handleMessage(Message msg){
super.handleMessage(msg);
Log.d(TAG, "handleMessage: name = " + Thread.currentThread().getName() + ", msg.what = " + msg.what);
}
};
发送消息的不同方法
使用handler发送消息时有几种不同的方法。
普通发信息
sendMessage(Message message)
直接立刻将message传输出去。
发送空消息
sendEmptyMessage(int what)
只传输message里面的what变量,是一个int值,通常用来发信号通知子线程做某些工作。
两种按时发消息
sendMessageAtTime (Message msg, long uptimeMillis)
sendEmptyMessageAtTime (int what, long uptimeMillis)
以上与下面这种:
sendMessageDelayed (Message msg, long delayMillis)
sendEmptyMessageDelayed (int what, long delayMillis)
其中atTime的功能是在固定的时刻uptimeMillis发送消息,如果uptimeMillis设定为500ms,那么开机500ms后这个消息就会被放到消息队列。
delayed的功能是在此刻的delayMillis延时后发送信息,如果delayMillis设定为500ms,那么在该行代码执行后的500ms这个消息就会放到消息队列。
以下两行代码的意思都是在该行代码执行之后延时1秒将消息放到消息队列中,SystemClock.uptimeMillis()是当前已经开机的时间。
mHandler.sendMessageAtTime(msg, SystemClock.uptimeMillis()+1000);
mHandler.sendMessageDelayed(msg, 1000)