练习心得
整个实现涉及Looper、Handler、MessageQueue、Message 4个类
- Looper:一个线程只能有一个Looper实例,通过Looper.prepare()获取实例,构造实例过程同时生成MessageQueue
- Handler:负责发送消息和处理消息(即负责收发)
- MessageQueue:一个线程仅能有一个,以队列先进先出的方式存储Handler发送的消息
- Looper.loop()方法以死循环的方式不断从MessageQueue拿取Message交给Handler处理,一定要放到最后一条语句,因为是死循环获取队列中的消息,会阻塞同一线程的其它语句执行。可以通过调用Looper.quit()终止死循环
- Message:消息载体,注意每次handler投递的message都要是一个新的实例,否则报IllegalStateException,This message is already in use
代码样例
/**
* Created by Rambo
*/
public class MyActivity extends MainActivity {
private EditText myEditText = null;
private Button stop = null;
private HashMap<String, String> asynTaskParams = new HashMap<>();
private Handler mainThreadHandler = null;
private Handler otherThreadHandler = null;
private final int UPDATE_EDITTEXT = 0x01;
private final int UPDATE_BUTTONTEXT = 0x02;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
myEditText = (EditText) findViewById(R.id.myEditText);
stop = (Button) findViewById(R.id.stop);
// 主线程定义handler用于处理其它线程发送过来的消息
mainThreadHandler = new Handler() {
/**
* 消息处理回调
* @param msg 消息信息
*/
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {// 通过msg.what区分消息来源
case UPDATE_EDITTEXT:
Log.v(TAG, "otherThread call MainThread handler running:" + Thread.currentThread().getName());
myEditText.setText(msg.getData().get("threadIndex").toString());
break;
case UPDATE_BUTTONTEXT:
Log.v(TAG, "timer call MainThread handler running:" + Thread.currentThread().getName());
stop.setText("stop" + msg.getData().get("timerIndex").toString());
break;
}
}
};
// 定义新线程,执行耗时任务
Thread otherThread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare(); // 创建非主线程的Looper,同时在Looper的构造方法中创建MessageQueue(先进先出队列),一个线程中只能有一个Looper和MessageQueue
// 非主线程处理器,其它线程可通过handler与该线程进行数据通讯,这也是线程间通讯的一种机制
otherThreadHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
default:
Log.v(TAG, "otherThread-otherThreadHandler.handleMessage");
}
}
};
Log.v(TAG, "otherThread running:" + Thread.currentThread().getName());
try {
for (int index = 0; index < 5; index++) {
// 定义要发给主线程handler的消息,每次handler投递的message都要是一个新的实例,否则报IllegalStateException,This message is already in use
Message otherThreadMsg = new Message();
otherThreadMsg.what = UPDATE_EDITTEXT;
Bundle data = new Bundle();
data.putInt("threadIndex", index);
Thread.sleep(1000);
otherThreadMsg.setData(data);
// 通过主线程handler实例发送消息,相当于自发自收
mainThreadHandler.sendMessage(otherThreadMsg);
}
} catch (Exception e) {
e.printStackTrace();
}
// 该语句触发Looper不断从MessageQueue中获取新消息交由handler处理,
// 一定要放到最后一条语句,因为是死循环获取队列中的消息,会阻塞同一线程的其它语句执行
Looper.loop();
}
});
otherThread.start();
// 定时任务,会起新的线程执行run代码块
new Timer().schedule(new TimerTask() {
@Override
public void run() {
Log.v(TAG, "TimerThread running:" + Thread.currentThread().getName());
try {
for (int index = 0; index < 5; index++) {
// 注意每次handler投递的message都要是一个新的实例,否则报IllegalStateException,This message is already in use
Message timerThreadMsg = new Message();
timerThreadMsg.what = UPDATE_BUTTONTEXT;
Bundle data = new Bundle();
data.putInt("timerIndex", index);
Thread.sleep(1000);
timerThreadMsg.setData(data);
mainThreadHandler.sendMessage(timerThreadMsg);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 0);// 表示不延迟
while (otherThreadHandler == null){
}
otherThreadHandler.sendEmptyMessage(0);
}
运行日志如下: