本章主要介绍Android的消息机制,Android的消息机制是由Handler来实现的,所以本章的重点就是Handler。
[Handler的使用]
Handler
是Android的基础,所以怎么去使用它也是一个基础。
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = 100;
handler.sendMessage(message);
}
}).start();
sendMessage
负责发送消息,handleMessage
负责接收消息并处理消息,发送消息在子线程,接收消息和处理消息在主线程。
以上代码的使用都比较熟悉了,那么它的Handler的实现原理是什么样子的呢?
在了解原理之前,我想首先需要了解下生产者/消费者设计模式
和ThreadLocal
。
[生产者/消费者设计模式]

我在网上找了一张图,这张图可以大致看出这个设计模式。
生产者
就相当于sendMessage
方法,将消息发出去,生产者
的发送只能在子线程发送,不能在主线程发送,多个生产者
可能在不同的子线程中。
生产者将数据
发送出去,这个数据就相当于Message
。
数据会存放在内存缓冲区
,这个缓冲区就是下文代码中的LinkedBlockingDeque
。
遍历内存缓冲区,将数据一个一个的取出
,下文代码中,将由Loop对象负责把数据取出。
最终,被取出的数据被消费者
处理,这里的消费者
就是handleMessage
方法。
生产者/消费者设计模式就说这么多,如果不理解,可以先去了解一下这个设计模式。
[ThreadLocal]
ThreadLocal
是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获取到存储的数据,对其它线程来说则无法获取到数据。
ThreadLocal<String> threadLocal = new ThreadLocal();
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = 100;
handler.sendMessage(message);
threadLocal.set("我是张三");
String str = threadLocal.get();
Log.d("yunchong", str);
threadLocal.remove();
}
}).start();
首先在方法的外面定义一个全局的ThreadLocal
对象,set
方法可以在ThreadLocal
中存储数据,get
方法可以获取ThreadLocal
中的数据,使用完数据之后可以清除ThreadLocal
中的数据。(清除数据是为了节省内存)
ThreadLocal
对象将在Handler架构中使用。
[有关对象]
Handler
:Handler
Message
:消息
MessageQueue
:存储消息的缓存队列
Looper
:遍历缓存队列中的消息,取出并处理
[手写Handler架构]
手写Handler架构没什么好说的,本人已经手写好几遍了,强烈建议不熟悉Handler架构的人亲自动手敲几遍。
public class Handler {
private MessageQueue messageQueue;
public Handler(){
Looper.prepare();
Looper looper = Looper.myLooper();
messageQueue = looper.messageQueue;
}
/**
* 接收消息并处理消息
* @param msg
*/
public void handleMessage(Message msg){
}
/**
* 发送消息
* @param msg
*/
public void sendMessage(Message msg){
//入队
messageQueue.enQueue(msg);
msg.target = this;
}
}
public class Message {
public int what;
//当使用Handler发送消息时,Hander对象就和Message绑定了
Handler target;
}
/**
* 消息队列
*/
public class MessageQueue {
//阻塞队列
private static BlockingDeque deque = new LinkedBlockingDeque(100);
/**
* 入队
* @param msg
*/
public void enQueue(Message msg){
try {
deque.put(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 出队
*/
public Message next(){
Message msg = null;
try {
msg = (Message) deque.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
return msg;
}
}
public class Looper {
private static ThreadLocal<Looper> threadLocal = new ThreadLocal<>();
public MessageQueue messageQueue;
private Looper(){
messageQueue = new MessageQueue();
}
/**
* 创建队列
*/
public static void prepare(){
if(threadLocal.get() != null){
throw new RuntimeException("Only one Looper may be created per thread");
}else{
threadLocal.set(new Looper());
}
}
/**
* Looper对象
* @return
*/
public static Looper myLooper(){
return threadLocal.get();
}
/**
* 循环消息
*/
public static void looper(){
for (;;){
//获取Looper对象
Looper looper = myLooper();
//获取队列
MessageQueue messageQueue = looper.messageQueue;
//取出消息
Message msg = messageQueue.next();
//处理消息
msg.target.handleMessage(msg);
}
}
}
代码调用:
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.d("yunchong", "what:"+msg.what);
}
};
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = 100;
handler.sendMessage(message);
}
}).start();
Looper.looper();
[本章完...]
网友评论