前言:
本编文章纯粹个人见解,如有错误或者不到位的地方,请大家指出,多谢。
组成:
一、Message
二、Handler
三、MessageQueue
四、Looper
介绍:
Message:
线程间通讯的信息载体。
可将关键的对象,数据装在一个Message类中发给其他线程(一般是主线程)。
Handler:
主要负责发送和处理Message。
MessageQueue:
主要负责存放由handler发出的Message。
每个线程只有一个MessageQueue对象。
Looper:
主要负责将MessageQueue中的Message拿个Handler处理。
每个线程只有一个Looper对象。
大致流程图:
上图来自郭霖的 《第一行代码》
(子)Handler → Message → MessageQueue → Message → Looper → Message → (主)Handler
如何使用:
第一步:在主线程新建一个Handler并重写handleMessage()方法。
第二步:在子线程新建一个Message类并打包好要发送的数据,调用handler.sendMessage()。
先来一个简单的例子:
子线程发送消息,改变button的内部文字
public class MainActivity extends AppCompatActivity {
private Button sendBtn;
private static final int CHANGE_BUTTON = 1;
private Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case CHANGE_BUTTON:
sendBtn.setText("Handler");
break;
}
//以前handlerMessage没有返回值,现在要返回boolean
//应该是根据boolean值判断handleMessage方法是否执行完毕
return true;
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendBtn = findViewById(R.id.sendBtn);
sendBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
msg.what = CHANGE_BUTTON;
mHandler.sendMessage(msg);
}
}).start();
}
});
}
}
效果图:
Message可以包含什么信息呢?
如果你觉得上面的博文还是不够包含你想发送的信息。
你可以自己创建一个类,把你想发的信息都装进去。
我做个小小的例子:
1.写个实体类
2.将实体类放进Bundle里,再将Bundle放进Message里
public class Data implements Serializable{
private String str;
private long l;
private float flo;
/* 以下省略setter 和 getter */
}
sendBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
//设置好自定义的实体类
Data data = new Data();
data.setStr("hello");
data.setL(32464651231234L);
data.setFlo(1.67f);
//将实体类放进Bundle里
Bundle mBundle = new Bundle();
mBundle.putSerializable("SER_KEY", data);
//使用setData将想发送的信息一起发出去
Message msg = new Message();
msg.what = CHANGE_BUTTON;
msg.setData(mBundle);
mHandler.sendMessage(msg);
}
}).start();
}
});
private Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case CHANGE_BUTTON:
Bundle bundle = msg.getData();
Data data = (Data) bundle.getSerializable("SER_KEY");
if (data != null) {
sendBtn.setText(data.getStr());
}
break;
}
return true;
}
});
Handler的优缺点:
优点:
结构比较清晰,如果有多个后台任务并行进行多个UI操作,Handler是很方便的。
缺点:
如果只有一个后台任务那就会显得代码过多和结构复杂。
因为我的例子只有封装信息,
根本没有进行后台耗时操作,例如I/O,网络,数据库操作,所以感觉不出来。