1.是啥?
Handler是一种异步消息分发机制。
因为子线程不能进行UI的更新,只有UI线程(即主线程)才可以进行UI的更新。所以需要Handler来接受子线程发送的数据,并用此线程配合主线程来更新UI。Handler可以完成主线程和子线程、子线程和子线程之间的通信。
2.怎么工作
使用Handler进行异步消息处理主要由以下四部分组成:
(1)Message,线程之间传递的消息,用于不同线程之间的数据交互。Message中的what字段用来标记区分多个消息,arg1、arg2 字段用来传递int类型的数据,obj可以传递任意类型的字段。
(2)Handler,用于发送和处理消息。其中的sendMessage()用来发送消息,handleMessage()用于消息处理,进行相应的UI操作。
(3)MessageQueue,消息队列(先进先出),用于存放Handler发送的消息,一个线程只有一个消息队列。
(4)Looper,可以理解为消息队列的管理者,当发现MessageQueue中存在消息,Looper就会将消息传递到handleMessage()方法中,同样,一个线程只有一个Looper。
Message可以携带的数据:
//通常作标志位,作区分
message.what;(int)
//携带简单数据
message.arg1;(int)
message.arg2;(int)
//携带object数据类型
message.obj;(object)
3.代码
package com.example.demolist;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import static com.example.demolist.R.layout.activity_main;
public class MainActivity extends AppCompatActivity {
public static final int UPDATE =0x1;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(activity_main);
textView = findViewById(R.id.tv);
begin();
}
private Handler handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what){
case UPDATE:
textView.setText(String.valueOf(msg.arg1));
break;
}
}
};
public void begin(){
new Thread(new Runnable() {
@Override
public void run() {
for (int i=5;i>0;i--){
Message msg = new Message();
msg.what = UPDATE;
msg.arg1 = i;
handler.sendMessage(msg);
try {
Thread.sleep(1000);//休眠1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
//打印log
Log.i("tag",MainActivity.this+"-"+ i);
}
//计时结束后跳转到其他界面
startActivity(new Intent(MainActivity.this,Main2Activity.class));
//添加finish方法在任务栈中销毁倒计时界面,使新开界面在回退时直接退出而不是再次返回该界面
finish();
}
}).start();
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:gravity="center"
android:textSize="30sp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="NO DATA"
android:id="@+id/tv"/>
</LinearLayout>
3.主线程向子线程发送消息
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final int SEND_MESSAGE = 10;
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new MyRunnable()).start();
findViewById(R.id.send_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message msg = Message.obtain();
msg.what = SEND_MESSAGE;
msg.obj = "主线程向子线程发送新的消息啦";
mHandler.sendMessage(msg);
}
});
}
private class MyRunnable implements Runnable {
@Override
public void run() {
//建立消息循环的步骤
Looper.prepare();//1、初始化Looper
mHandler = new Handler() {//2、绑定handler到CustomThread实例的Looper对象
public void handleMessage(Message msg) {//3、定义处理消息的方法
if (msg.what == SEND_MESSAGE) {
Log.i(TAG, "handleMessage:---->" + msg.obj);
}
}
};
Looper.loop();//4、启动消息循环
}
}
}
4.子线程向主线程发送消息
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final int UPDATE_TEXT = 1;
private TextView textView;
private Button button;
private HandlerTest handlerTest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView=findViewById(R.id.text_view);
button=findViewById(R.id.button);
handlerTest=new HandlerTest();
button.setOnClickListener(this);
}
private class HandlerTest extends android.os.Handler {
@Override
public void handleMessage(@NonNull Message msg) {
if(msg.what==UPDATE_TEXT){
textView.setText(String.valueOf(msg.obj));
}
}
}
@Override
public void onClick(View view) {
switch(view.getId()){
case R.id.button:
new Thread(new Runnable() {
@Override
public void run() {
Message message=new Message();
message.obj="来自子线程的消息";
message.what=UPDATE_TEXT;
handlerTest.sendMessage(message);
}
}).start();
default:
break;
}
}
}
5.内存泄漏问题
https://www.jianshu.com/p/ed9e15eff47a