handlerThread是内部有一个looper轮询器的Thread线程。HandlerThread,是一个具有Looper的线程,这个Looper可以用于创建Handler;另外start()必须执行,因为Handler毕竟是个Thread,调用start()会走到run()中,而HandlerThread恰恰是在run中创建的Looper。
HandlerThread产生的背景:
google为了避免以下几种情况,给android开发者提供了这样一个异步框架:
- 在需要做子线程耗时操作时,我们有可能会new Thread来进行
- 频繁多次创建子线程,对性能是有影响的
- 可以自己在子线程中使用looper轮询,避免多次创建线程
HandlerThread特点:
- HandlerThread是一个线程类,它继承了Thread
- 它的内部有自己的Looper对象,可以进行loop轮询
- 使用HandlerThread的looper创建的Handler在handleMessage中可以进行耗时操作,因为它是执行在子线程的
- 它的优点是不会阻塞主线程,缺点是不能同时执行多任务,需要有序执行,执行效率低。
HandlerThread其实就是一个线程;HandlerThread比较适用于单线程+异步队列的场景,比如IO读写操作数据库、文件等,耗时不多而且也不会产生较大的阻塞。对于网络IO操作,HandlerThread并不适合,因为它只有一个线程,还得排队一个一个等着。
适用于子线程多任务的工作场景。如:在工作线程中进行多个网络请求,多个I/O操作,最典型的应用就是 IntentService
HandlerThread的本质:继承Thread类 + 封装Handler类 + Looper()
一、用法
- 在主线程中新建一个 HandlerThread 对象,然后调用 start() 方法启动该线程。
- 创建一个主线程Handler 对象,关联APP主Looper对象,用于子线程与主线程之间的沟通。
- 创建一个工作线程Handler 对象,关联 HandlerThread 的 Looper 对象。
- 发送消息给工作线程,工作线程Handler 接收消息,并处理消息,然后调用主线程。Handler,发送信息给主线程,通知主线程做UI工作。
- 当对应的 Activity 销毁时,退出 HandlerThread,终止消息循环。
// 步骤1:创建HandlerThread实例对象
// 传入参数 = 线程名字,作用 = 标记该线程
HandlerThread mHandlerThread = new HandlerThread("handlerThread");
// 步骤2:启动线程
mHandlerThread.start();
// 步骤3:创建工作线程Handler & 复写handleMessage()
// 作用:关联HandlerThread的Looper对象、实现消息处理操作 & 与其他线程进行通信
// 注:消息处理操作(HandlerMessage())的执行线程 = mHandlerThread所创建的工作线程中执行
Handler workHandler = new Handler( mHandlerThread.getLooper() ) {
@Override
public boolean handleMessage( msg) {
...//消息处理
return true;
}
});
// 步骤4:使用工作线程Handler向工作线程的消息队列发送消息
// 在工作线程中,当消息循环时取出对应消息 & 在工作线程执行相关操作
// a. 定义要发送的消息
Message msg = Message.obtain();
msg.what = 2; //消息的标识
msg.obj = "B"; // 消息的存放
// b. 通过Handler发送消息到其绑定的消息队列
workHandler.sendMessage(msg);
// 步骤5:结束线程,即停止线程的消息循环
mHandlerThread.quit();
二、下载示例
activity_handler_thread.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".HandlerThreadDemo.HandlerThreadActivity">
<Button
android:id="@+id/bt_start_download"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始下载"
android:textSize="22sp"
/>
</RelativeLayout>
HandlerThreadActivityTwo.java
public class HandlerThreadActivityTwo extends AppCompatActivity {
private static final String TAG = "HandlerThreadActivityTwo";
private Handler handler;
private HandlerThread handlerThread;
private Button bt_start_download;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_thread);
bt_start_download = (Button) findViewById(R.id.bt_start_download);
bt_start_download.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//开启下载线程
Handler dowmhandler = DownloadHandler();
if(dowmhandler != null){
dowmhandler.post(new DownloadThread(100));
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
}
///开启一个下载任务
private Handler DownloadHandler(){
if(handler == null){
// 步骤1:创建HandlerThread实例对象
// 传入参数 = 线程名字,作用 = 标记该线程
handlerThread = new HandlerThread("download");
// 步骤2:启动线程
handlerThread.start();
// 步骤3:创建工作线程Handler & 复写handleMessage()
// 作用:关联HandlerThread的Looper对象、实现消息处理操作 & 与其他线程进行通信
// 注:消息处理操作(HandlerMessage())的执行线程 = mHandlerThread所创建的工作线程中执行
handler = new Handler(handlerThread.getLooper());
}
return handler;
}
//开启下载进度线程
private class DownloadThread implements Runnable{
private int start = 0;
private int progres;
public DownloadThread(int progres) {
this.progres = progres;
}
@Override
public void run() {
while(start <= progres){
Log.i("下载进度", ": "+start);
start += 10;
}
}
}
}
三、多任务使用
activity_handler_thread.xml
<Button
android:id="@+id/bt_more_start_download"
android:layout_below="@id/bt_quit_download"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始多下载"
android:textSize="22sp"
/>
<Button
android:id="@+id/bt_more_quit_download"
android:layout_below="@id/bt_more_start_download"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="退出多下载"
android:textSize="22sp"
/>
HandlerThreadActivityTwo.java
bt_more_start_download.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Handler dowmhandler = MultDownloadHandler();
//任务1
// 通过sendMessage()发送
// a. 定义要发送的消息
Message msg = Message.obtain();
msg.what = 2; //消息的标识
msg.obj = "A"; // 消息的存放
// b. 通过Handler发送消息到其绑定的消息队列
dowmhandler.sendMessage(msg);
//延时发送
try {
//延时操作
Thread.sleep(2000);
Log.i("TAG", "延时发送");
} catch (InterruptedException e) {
e.printStackTrace();
}
//任务2
// 通过sendMessage()发送
// a. 定义要发送的消息
Message msg2 = Message.obtain();
msg2.what = 1; //消息的标识
msg2.obj = "B"; // 消息的存放
// b. 通过Handler发送消息到其绑定的消息队列
dowmhandler.sendMessage(msg2);
}
});
bt_more_quit_download.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handlerThread.quit();
Log.i("TAG", "退出成功");
bt_more_quit_download.setText("多下载退出成功");
}
});
///开启多个下载任务
private Handler MultDownloadHandler(){
if(handler == null){
// 步骤1:创建HandlerThread实例对象
// 传入参数 = 线程名字,作用 = 标记该线程
handlerThread = new HandlerThread("multdownload");
// 步骤2:启动线程
handlerThread.start();
// 步骤3:创建工作线程Handler & 复写handleMessage()
// 作用:关联HandlerThread的Looper对象、实现消息处理操作 & 与其他线程进行通信
// 注:消息处理操作(HandlerMessage())的执行线程 = mHandlerThread所创建的工作线程中执行
handler = new Handler(handlerThread.getLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what){
case 1:
Log.i("TAG", "1任务开始下载 ");
break;
case 2:
Log.i("TAG", "2任务开始下载 ");
break;
default:
break;
}
}
};
}
return handler;
}