一、前言
在Android应用的开发中,Handler的使用是必不可少的,包括目前的面试也都比较喜欢问这一类的问题,所以感觉我们现在不了解Handler都不好意思开口说做Android应用开发的了。抱着最近一段时间对Handler源码的了解,决定通过模拟Handler的实现,来表达和记录下我对Handler内部关系和消息发送之间的简化关系。
二、Handler的实现关系
在查看Handler源码的过程中,通过抽丝剥茧的方式,我们可以看到实现Handler消息发送机制,主要组成有这几个类:Handler、Looper、MessageQueue、Message,
其之间的关系图如下:
图有点简陋,不过我们还是可以清晰了解到,它们采用了生产和消费的这种方式进行消息的分发,Handler通过sendMessage的方法把消息生产到MessageQueue的队列,Looper类里面有个对MessageQueue的
死循环,发现MessageQueue中有消息过来,就调用Message中持有的target,即Handler,进行dispatchMessage消息转发,从而完成了整个消息机制的闭环。(当然,这里是对源码的一个简化描述,真正的消息内容传过去还得从底层经过了IPC通信等一系列复杂的环节,不过这不影响我们借此来理解Handler)
好了,接下来看我们的代码实现:
三、代码实现
1、Message.java类
public class Message {
public int what;
public int arg1;
public int arg2;
public Object obj;
Handler target;
Runnable callback;
public Message(){
}
}
2、MessageQueue.java类
public class MessageQueue {
private final int MAX_SIZE = 10;
/**阻塞的队列*/
ArrayBlockingQueue<Message> queue = new ArrayBlockingQueue<Message>(MAX_SIZE);
public void enqueueMessage(Message msg){
try {
queue.put(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public Message next(){
try {
return queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
3、Handler.java类
public class Handler {
private Looper mLooper;
private MessageQueue mQueue;
/**
* 使用默认无参构造函数创建Handler的时候,从我们查看
* 源码知道,获取的是应用入口ActivityThread类的main函数中,调用了prepare方法所创建的Looper对象,
* 这里获取到的就是主线程的Looper
*/
public Handler(){
mLooper = Looper.myLooper();
mQueue = mLooper.mQueue;
}
/**
* 在这里传进了Looper对象,那就与创建该Looper所在的线程关联
*/
public Handler(Looper looper){
mLooper = looper;
mQueue = mLooper.mQueue;
}
Callback mCallback;
public final void sendMessage(Message msg){
msg.target = this;
mQueue.enqueueMessage(msg);
}
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
public interface Callback {
public boolean handleMessage(Message msg);
}
}
public class Looper {
/**多线程数据隔离*/
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
MessageQueue mQueue;
private Looper(){
mQueue = new MessageQueue();
}
public static void prepare(){
if(sThreadLocal.get() != null){
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static Looper myLooper() {
return sThreadLocal.get();
}
public static void loop(){
final Looper me = myLooper();
if(me == null){
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
msg.target.dispatchMessage(msg);
}
}
}
5、测试类DemoTest.java,这里开启了10条线程来模拟不停给Handler发送消息,然后从Handler的回调handleMessage来进行回调打印显示。
public class DemoTest {
public static void main(String[] args){
Looper.prepare();
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
System.out.println("handleMessage---->"+msg.obj.toString());
}
};
for(int i = 0 ; i < 10 ; i ++){
new Thread(){
@Override
public void run() {
while(true){
Message msg = new Message();
msg.obj = "发送消息:"+Thread.currentThread().getName();
handler.sendMessage(msg);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
Looper.loop();
}
}
6、打印结果
四、疑问回调
1、在测试类DemoTest中的main函数中,我们调用了Looper.loop(),不会发生死循环吗?
答:我想说,这本身就是程序的入口,好比源码里面的ActivityThread类的main函数,一旦跳出,那进程也就跟着结束了。
2、这样创建的Handler是在什么线程,UI主线程吗?
答:首先,这里只是一个普通的Java工程,没有UI主线程这一说法,其实Android里面的UI主线程也是相对来说的,在ActivityThread的被称为UI线程,这个之外的都被称为非UI子线程。那么在这里,我们的main里面创建的Handler就等于是一个主线程。
3、
那如何创建一个使用子线程Looper的Handler?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//tv_show = (TextView)findViewById(R.id.tv_show);
System.out.println("onCreate:"+Thread.currentThread().getName());
new Thread(){
@Override
public void run() {
System.out.println("run:"+Thread.currentThread().getName());
Looper.prepare();
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
System.out.println("handleMessage:"+Thread.currentThread().getName());
}
};
handler.sendEmptyMessage(0);
Looper.loop();
}
}.start();
}
打印的结果:
01-18 09:09:00.915 22009-22009/com.lsy.handerdemo I/System.out: onCreate:main
01-18 09:09:00.920 22009-22062/com.lsy.handerdemo I/System.out: run:Thread-221
01-18 09:09:00.925 22009-22062/com.lsy.handerdemo I/System.out: handleMessage:Thread-221
handleMessage处理的结果是在子线程的,这个时候我们创建的这个handler使用的是Looper.prepare()在子线程创建的Looper,所以在loop循环消息分发的时候,也在子线程里面进行回调。
五、总结
当然Handler和Looper内部的实现不可能那么简单,还要比这复杂得多很多,不过通过这样的一个模拟过程,至少可以加深我们对Handler机制的了解,何尝不是一件好事呢。