上一篇扒开AsyncTask的祖坟的时候提到了Handler,说白了AsyncTask只是对Handler进行了封装,这次就进一步研究一下Handler机制,我写了个模拟handler机制的Demo (https://github.com/wk415190639/Looper),提及handler必然涉及到Looper、Message、MessageQueue,这几个类Handler机制主要组成部分,先分析一下这个Demo
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new ReceiveThread().start();
startActivity(new Intent(this,WorkActivity.class));
}
}
MainActivity 里做了两件事,第一是开启了模拟的UI线程,第二就是开启WorkActivity,简单到极致,没什么可说的了,看看WorkActivity里面做了什么
public class WorkActivity extends Activity implements View.OnClickListener {
HandlerTest handlerTest = new HandlerTest() {
@Override
public void handleMessage(MessageTest msg) {
super.handleMessage(msg);
Log.i("QueueTest", Thread.currentThread().getName() + " : handleMessage : " + msg.msg);
}
};
int i = 100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.currentThread().setName("workThread");
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(this);
}
@Override
public void onClick(View view) {
MessageTest msg = new MessageTest();
msg.msg = i++;
Log.i("QueueTest", Thread.currentThread().getName() + " : sendMessage : " + msg.msg);
handlerTest.sendMessage(msg);
}
}
WorkActivity 里面先以匿名内部类的方式实例化一个HandlerTest类,这和平时我们获取handler的方式一样。在OnCreate()回调里将当前的线程名设置为workThread,这个线程原本为真正的UI线程,为了Demo的演示效果就把Android原本的UI线程和工作线程兑换了名字。接着注册了Button的点击事件,在Button的onClicks事件里发送消息。也就是让HandlerTest把消息放进消息队列。HandlerTest类也是非常简单的。
public class HandlerTest {
public LinkedBlockingDeque linkedBlockingDeque;
public HandlerTest() {
linkedBlockingDeque = LooperTest.myLooper().queue;
}
public void handleMessage(MessageTest msg) {
}
public void dispatchMessage(MessageTest msg) {
handleMessage(msg);
}
public final boolean sendMessage(MessageTest msg) {
msg.target = this;
linkedBlockingDeque.offer(msg);
return true;
}
}
在handlerTest类里有三个方法sendMessage是写给工作线程通过handler调用的,这个函数主要是把Message放进了消息队列linkedBlockingDeque里,这个linkedBlockingDeque是在handlertest类构造函数里赋值的,dispatchMessage函数也是主要是为了调用handleMessage函数,可以看到handleMessage函数里是空的,他的逻辑是在WorkActivity里以匿名内部类t的方式被复写的。所以真正的逻辑是在workActivity.java里,再去看看linkedBlockingDeque的真正位置LooperTest里都做了什么
public class LooperTest {
public LinkedBlockingDeque<MessageTest> queue;
public Thread thread;
private static LooperTest looperTest;
public LooperTest() {
queue = new LinkedBlockingDeque<MessageTest>();
thread = Thread.currentThread();
}
public static void prepareMainLooper() {
if (looperTest == null)
looperTest = new LooperTest();
}
public static @Nullable LooperTest myLooper() {
return looperTest;
}
public void loop() {
for (; ; ) {
try {
Log.i("QueueTest", Thread.currentThread().getName() + " : start blocking....................");
MessageTest msg = (MessageTest) queue.take();
msg.target.dispatchMessage(msg);
Log.i("QueueTest", Thread.currentThread().getName() + " : read msg : " + msg.msg + "\n\n ");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
LooperTest 在构造函数中实例化的一个消息队列,prepareMainLooper()实例化了LooperTest,myLooper()返回LooperTest实例,Loop()就是循环读取消息队列里面的数据,当消息队列为空时会一直阻塞在哪里,直到读取到消息队列中的数据,接着调用HandlerTest的dispatchMessage()方法,在dispatchMessage()调用handleMessage(),这样WorkActivity$HandlerTest 的handleMessage()就被调用了,因为是在LooperTest所在线程调用的,所以handleMessage()会运行在LooperTest所在的线程里,也就是最开始MainActivity开启的那个ReceiveThread线程,如果他是UI线程,那么handleMessage()就会运行在UI线程了。在回过来看一看在最开始的是开启的那个线程都做什么工作
public class ReceiveThread extends Thread {
public ReceiveThread() {
setName("ReceiveThread");
}
@Override
public void run() {
LooperTest.prepareMainLooper();
LooperTest looperTest = LooperTest.myLooper();
looperTest.loop();
}
}
这个类主要的工作就是实例化了Looper,然后让Looper循环读取消息队列的消息,再将消息发给HandlerTest。下面送一张蜘蛛网图和点击一次的效果
I/QueueTest: ReceiveThread : start blocking....................
I/QueueTest: workThread : sendMessage : 100
I/QueueTest: ReceiveThread : handleMessage : 100
I/QueueTest: ReceiveThread : read msg : 100
I/QueueTest: ReceiveThread : start blocking....................
接下来看看Android源码吧
先从Handler看看吧
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
这里边看似平常却暗藏玄机,去Handler的构造函数看一下
public Handler() { this(null, false); }
public Handler(Callback callback, boolean async) {
略。。。。。。
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
略。。。。。。。
}
略。。。。。。
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
略。。。。。。。
}
代码里略掉了一些无关部分,构造函数里主要是获取了所在线程的Looper实例和Looper实例下的mQueue消息队列。主线程的Looper是在ActivityThread的main方法里被实例化的(下次研究一下Looper如何在ActivityThread里实例化的),ActivityThread 就相当于Demo里写的ReceiveThread的那个类,这里先不做研究。再handler是如何发送消息的,一般我们会调用sendMessage(Message msg),那就进去看看他的实现
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
跟到这里可以发现Message实例的成员target被赋值为当前的handler实例,然后就把msg推进了消息队列里面,到这里消息的发送就结束了,那在去看看消息再UI线程里是怎么接收的吧,像Demo里所写的那样,Message 是在Looper 类的loop()函数里被接收的,那就跳进去看看,
public static void loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
msg.target.dispatchMessage(msg);
}
}
删去了一些碍眼的代码,就剩下这几句骨干了,loop()里循环读取queueu里的数据,读到数据消息后调用message的成员对象target(也就是handler)的dispatchMessage(msg)方法,将收到的消息分发出去
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
在这里边调用了 handleMessage(msg),之后再上面写的匿名内部类(new Handler(){})的handleMessage()里就能接收到消息了。到这里handler的消息发送到接收全找到了。