多线程—HandlerThread
2020-02-10 本文已影响0人
似焰如火
1. 简单说明
- 定义:Android提供的已经封装好的轻量级异步类
- 作用:实现主线程和工作线程之间通信
- 有点:方便实现异步通信,避免使用Handler+Thread的复杂组合
- 原理:对Handler进行了封装;继承Thread类,并创建一个带有Looper的工作线程;
2. 使用步骤
// 第1步:先创建HandlerThread对象
// 传入参数即线程名字,用于标记该线程
HandlerThread mHandlerThread = new HandlerThread("handlerThread");
// 步骤2:启动线程
mHandlerThread.start();
// 步骤3:给工作线程创建Handler 并重写handleMessage()方法
// 创建Handler时,要关联HandlerThread的Looper对象,此时消息处理操作的执行线程就是 mHandlerThread所创建的工作线程。必须保证这个工作线程已经start,否则还没有Looper对象。
Handler workHandler = new Handler( mHandlerThread.getLooper() ) {
@Override
public void handleMessage(Message msg) {
...//消息处理
}
});
// 步骤4:在主线程中使用给工作线程创建的workHandler ,向工作线程的消息队列发送消息
// a. 定义要发送的消息
Message msg = Message.obtain();
msg.what = 2; //消息的标识
msg.obj = "B"; // 消息的存放
// b. 通过Handler发送消息到其绑定的消息队列
workHandler.sendMessage(msg);
// 步骤5:结束线程,即停止线程的消息循环
mHandlerThread.quit();
3. 举个例子
- 布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.47"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.313" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="600dp"
android:layout_marginEnd="10dp"
app:layout_constraintBottom_toTopOf="@+id/show"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Button
android:id="@+id/bt0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="start" />
<Button
android:id="@+id/bt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="delay 1s" />
<Button
android:id="@+id/bt2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="delay 3s" />
<Button
android:id="@+id/bt3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stop" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
- 源代码
public class MainActivity extends AppCompatActivity {
Handler mainhandler,workhandler;
boolean flag_start =false;
HandlerThread mHandlerThread;
protected TextView show;
Button bt0,bt1,bt2,bt3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show = findViewById(R.id.show);
bt0 = findViewById(R.id.bt0);
bt1 = findViewById(R.id.bt1);
bt2 = findViewById(R.id.bt2);
bt3 = findViewById(R.id.bt3);
bt0.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
flag_start = true;
show.setText("开始");
mHandlerThread = new HandlerThread("myHandlerThread");
mHandlerThread.start();
mainhandler = new Handler();
workhandler = new Handler(mHandlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 1:
try {Thread.sleep(1000);} catch (InterruptedException e) {}
mainhandler.post(new Runnable() {
@Override
public void run() {
show.setText("延时1秒");
}
});
break;
case 2:
try {Thread.sleep(3000);} catch (InterruptedException e) {}
mainhandler.post(new Runnable() {
@Override
public void run() {
show.setText("延时3秒");
}
});
break;
default:
Log.d("HandlerThreadTest","message error");
break;
}
}
};
}
});
bt1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(flag_start == true){
Message msg = Message.obtain();
msg.what = 1;
workhandler.sendMessage(msg);
}
}
});
bt2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(flag_start == true){
Message msg = Message.obtain();
msg.what = 2;
workhandler.sendMessage(msg);
}
}
});
bt3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
flag_start = false;
mHandlerThread.quit();
show.setText("停止");
}
});
}
}
- 补充知识点
- 在主线程中定义了Handler, 实现了handleMessage()方法, 在其它线程调用sendMessage后, looper中的MessageQueue会收到该Message, 但如果此时主线程正忙, 该消息不会被处理. 当主线程空闲时, Looper才会去查看MessageQueue中的消息, 并调用handleMessage进行处理.