首先,我们先别管Android中的消息机制,我们先来看一个需求:
在主线程中启动一个子线程去做一些事情,我希望子线程在做完这些事情后唤醒主线程来做一些相应的动作。
先想想怎么实现这个功能。直接在子线程回调一个接口?显然不行!
要让主线程感知到子线程的事情是否做完了。一般来说,就是在子线程完成事情后发送一些消息给主线程,让主线程知道子线程已经完成了工作,然后主线程去做相应的处理。这样一来,主线程就要变成一个死循环,无限循环的从消息队列中获取从子线程来的消息,并处理。
图中,主线程是一个轮询线程,主线程要做的事情就是,不断从消息队列中获取消息,并做处理。子线程处理完相关的业务之后,发送一个消息到消息队列中。整个过程是异步的。
同步:主线程启动一个子线程,在子线程执行过程中,主线程等待子线程完成后才继续往下运行
异步:主线程启动一个子线程,在子线程执行过程中,主线程也在运行
我们建立一个Java项目,简单模仿一下Android的消息机制
Looper是用来将线程变成一个轮询线程
package com.zhanjixun;
import java.util.HashMap;
import java.util.Map;
public class Looper {
private static Map<Long, Looper> mLoopers = new HashMap<Long, Looper>();
private MessageQueue mQueue = new MessageQueue();
private Looper() {
}
public static void prepare() {
long id = Thread.currentThread().getId();
if (mLoopers.get(id) != null) {
throw new RuntimeException("这线程的Looper已经调用prepare()");
}
mLoopers.put(id, new Looper());
}
public static void loop() {
while (true) {
Message next = myLooper().getMessageQueue().next();
if (next != null) {
if (next.getTarget() == null) {
return;
} else {
next.getTarget().handlerMessage(next);
}
}
}
}
public static Looper myLooper() {
Looper looper = mLoopers.get(Thread.currentThread().getId());
if (looper == null) {
throw new RuntimeException(Thread.currentThread().getName()
+ "线程的Looper还没有调用prepare()");
}
return looper;
}
public MessageQueue getMessageQueue() {
return mQueue;
}
}
其中的MessageQueue是用来管理Message的队列数据结构,先进先出原则
package com.zhanjixun;
import java.util.LinkedList;
public class MessageQueue {
private LinkedList<Message> mMsgs = new LinkedList<>();
public void push(Message msg) {
System.out.println("有消息进队列-->>>" + msg.toString());
mMsgs.add(msg);
}
public Message next() {
if (mMsgs.size() > 0) {
Message removeFirst = mMsgs.removeFirst();
System.out.println("有消息从队列被取出<<<---" + removeFirst.toString());
return removeFirst;
}
return null;
}
}
Message类是对要发送的消息的一个封装
package com.zhanjixun;
public class Message {
public int what;
public Object obj;
private Handler target;
public Handler getTarget() {
return target;
}
public void setTarget(Handler target) {
this.target = target;
}
}
Handler负责发送Message以及轮询线程回调
package com.zhanjixun;
/**
* Handler负责发送Message以及轮询线程回调
*
* @author doudian
*
*/
public class Handler {
private Looper myLooper;
/**
* 创建Handler一定要在轮询线程中创建,因为创建的时候需要获取轮询线程的Looper
*/
public Handler() {
myLooper = Looper.myLooper();
}
public void sendMessage(Message message) {
message.setTarget(this);
myLooper.getMessageQueue().push(message);
}
public void handlerMessage(Message message) {
}
}
最后在Main方法中调用试试看成果
package com.zhanjixun;
public class Main {
public static void main(String[] args) {
Looper.prepare();
Handler handler = new Handler() {
@Override
public void handlerMessage() {
System.out.println(" doing something in "
+ Thread.currentThread().getName() + " thread");
}
};
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(" doing something in "
+ Thread.currentThread().getName() + " thread");
handler.sendMessage(new Message());
}
}).start();
Looper.loop();
throw new RuntimeException("主线程不小心停止了!");
}
}
运行结果
源代码:http://download.csdn.net/detail/zhanjixun/9582075
写到这里大概就能明白整个消息机制的原理了:就是将主线程(也可以是其他子线程)变成一个死循环的线程,不断从队列中获取消息并处理;子线程处理一些业务,处理完毕就发送一个消息到消息队列中。
有空在分析一下Android中消息机制的源码