一. Handler作用
大多数博客上描述的Handler作用是线程间通信,这个描述其实不算准确,因此一度让我困惑于一个问题,如果只是实现线程间的通信,我在一个线程中设置另一个线程的回调,也能实现通信,为什么要用Handler?
于是看了下SDK上Handler类的解释:
翻译过来就是:
Handler有两个主要用途:
(1)调度消息和在未来某个时间点执行的运行库;
(2)入队一个在不同线程上执行的操作。
很明显,Handler的作用更多在于消息调度和切换执行线程。
二. Handler简介
提到Handler机制,源码解释网上有很多,基本都分析得很细,这里就不多说了,大概解释一下,Handler , Message , MessageQueue,Looper
Handler: 消息发送/接收器,发送的消息实时进入消息队列。
Message: 基于对象池模式的消息载体,内部属性包含发送器Handler,消息延时时间等相关内容。
MessageQueue:基于链表的消息队列,消息入队列时会对消息排序,时间由小到大排序。
Looper: 消息迭代器,用于从消息队列MessageQueue中迭代出有效消息Message,从Message取出Handler,执行Handler的dispatchMessage进行消息分发,最终进入到Runnable的run方法,或Handler的CallBack接口的handleMessage方法。
/**
* Handle system messages here.
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
三. 基于Handler机制,实现切换执行线程
MainActivity.class简单示例代码如下:
Thread1 t1;
Thread2 t2;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
......//省略部分代码
t1 = new Thread1();
t2 = new Thread2();
t1.setName("Thread1");
t2.setName("Thread2");
t2.start();
t1.start();
}
class Thread1 extends Thread implements Handler.Callback {
private Handler handler;
@Override
public void run() {
super.run();
do{
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
Logger.d("Thread1 run t2.isStart() = " + t2.isStart());
}while (!t2.isStart());
Looper.prepare();
handler = new Handler(Looper.myLooper(),this);
Message message = Message.obtain();
message.what = 1;
message.obj = "send from Thread1";
t2.getHandler().sendMessageDelayed(message,1000);
Looper.loop();
}
public Handler getHandler() {
return handler;
}
@Override
public boolean handleMessage(@NonNull Message msg) {
Logger.d("Thread1 ThreadName " + ((String) msg.obj) + " , data = " + msg.what + " ,currentThread = " + Thread.currentThread());
Message message = Message.obtain();
message.what = msg.what + 1;
message.obj = "send from Thread1";
t2.getHandler().sendMessageDelayed(message,1000);
return false;
}
}
class Thread2 extends Thread implements Handler.Callback {
private Handler handler;
boolean isStart = false;
@Override
public void run() {
super.run();
Looper.prepare();
handler = new Handler(Looper.myLooper(),this);
isStart = true;
Looper.loop();
}
public Handler getHandler() {
return handler;
}
@Override
public boolean handleMessage(@NonNull Message msg) {
Logger.d("Thread2 ThreadName " + ((String) msg.obj) + " , data = " + msg.what + " ,currentThread = " + Thread.currentThread());
Message message = Message.obtain();
message.what = msg.what + 1;
message.obj = "send from Thread2";
t1.getHandler().sendMessageDelayed(message,1000);
return false;
}
public boolean isStart() {
return isStart;
}
}
按照以上代码执行,结果如图所示:
从上图可以看出:在线程Thread1上创建的消息,发送后实际执行在Thread2上,反之亦如此。
若此时使用的不是handler而是线程实例直接回调线程方法,以第一条日志为例,则此时的第一条日志的currentThread将会是Thread1而非Thread2 , 由此可见,Handler入队了一个在不同线程上执行的操作.