Hi~ 我们来说说Android的消息处理机制
消息处理机制
相关类
- Message:消息,其中包含了消息ID,处理对象和处理数据,由MessageQueue统一队列管理,最终由Handler处理。
- Handler:负责Message发送和处理。
- MessageQueue:消息队列,按照FIFO原则存放消息。
- Looper:消息泵,来处理MessageQueue中的Message。
Message,MessageQueue,Handler,Looper之间的关系
看代码
Looper.class
变量
/**
* 用于管理Looper
*/
static final ThreadLocal sThreadLocal = new ThreadLocal();
/**
* 持有主线程Looper
*/
private static Looper sMainLooper; // guarded by Looper.class
/**
* 每个Looper持有一个消息队列
*/
final MessageQueue mQueue;
/**
* 每个Looper持有一个线程
*/
final Thread mThread;
方法
/**
* 创建一个Looper
*/
public static void prepare() {
prepare(true);
}
/**
* 真实的创建Looper的方法
* @param quitAllowed
*/
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
/**
* 初始化一个主线程的Looper,只能创建一个在启动应用的时候已经调用并创建。所以不需要我们自己去创建,否则会抛出异常。
*/
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
/**
* 返回一个主线程的上的Looper
*/
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
/**
* 进行消息循环,获取消息,发送消息
*/
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);
......
}
}
/**
* 返回一个当前线程中的Looper
* @return
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
/**
* 返回消息队列
* @return
*/
public static @NonNull MessageQueue myQueue() {
return myLooper().mQueue;
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
/**
* 判断当前线程是否和Looper的线程相同
* @return
*/
public boolean isCurrentThread() {
return Thread.currentThread() == mThread;
}
MessageQueue.class
/**
* 消息入队列,按时顺序进行排序存储
*
* @param msg 消息实体
* @param when 消息发送时间
* @return
* */
boolean enqueueMessage(Message msg, long when) {
......
synchronized (this) {
.....
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
/**
* 把消息放到消息队列的头上,需要唤醒
*/
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
/**
* 把消息插入到合适的位置
*/
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
//说明即便msg是异步的,也不是链表中第一个异步消息,所以没必要唤醒了
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
这里有个syncBarrier(同步分割栏)但是对其操作都是@hide,使用还还需要用java反射机制。
barrier的作用就是在某个时间阻拦不是异步的消息,如果需要继续获取消息必须把这个barrier给remove掉。
Message.class
/**
* 消息实体的唯一标示
*/
public int what;
/**
* 消息实体参数
*/
public int arg1;
/**
* 消息实体参数
*/
public int arg2;
/**
* 消息实体中的存储对象
*/
public Object obj;
/**
* 发送时间
*/
/*package*/ long when;
/**
* 消息实体中所带的数据
*/
/*package*/ Bundle data;
/**
* 处理对象
*/
/*package*/ Handler target;
/**
* 回调方法
*/
/*package*/ Runnable callback;
/**
* 消息对象池
*/
private static Message sPool;
/**
* 消息对象个数
*/
private static int sPoolSize = 0;
/**
* 默认最大个数为50
*/
private static final int MAX_POOL_SIZE = 50;
Message不能通过new创建对象应该通过obtain方法获取Message对象,因为为了避免大量的创建Message对象,Message会通过自身维护的一个对象池取Message对象。
obtain方法
- public static Message obtain()
- public static Message obtain(Message orig)
- public static Message obtain(Handler h)
- public static Message obtain(Handler h, Runnable callback)
- public static Message obtain(Handler h, int what)
- public static Message obtain(Handler h, int what, Object obj)
- public static Message obtain(Handler h, int what, int arg1, int arg2)
- public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj)
设置处理者
- public void setTarget(Handler target)
发送消息给处理者
- public void sendToTarget()
处理捆绑数据
- public Bundle getData()
- public Bundle peekData()
- public void setData(Bundle data)
Handler.class
/**
* 处理消息接口
*/
public interface Callback {
public boolean handleMessage(Message msg);
}
/**
* 实现这个方法处理消息
*/
public void handleMessage(Message msg) {
}
/**
* 这个是当mssage.callback不会空的时候执行
* @param message
*/
private static void handleCallback(Message message) {
message.callback.run();
}
/**
* 由Looper在获取消息后调用,这里是处理消息的逻辑
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
/**
* 如果message中没有callback函数,就直接执行handler中的静态方法handleMessage
*/
handleCallback(msg);
} else {
/**
* 如果Handler中定义了mCallback,那么先去执行mCallBack中的内容。
* 如果mCallback返回true,说明被mCallback中的handleMessage处理完成不在需要后续的Handler中的handleMessage处理
* 如果mCallback返回false,说明mCallback中的handleMessage没有处理完消息,后续有Handler中的handleMessage继续处理
*/
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
这里有两个handleCallback,一个是静态的方法,一个是普通方法;在调用的时机不一样,静态方法是在Message中定义了callback的时候调用的。
dispatchMessage()方法的处理消息逻辑
- 第一步:如果message中没有callback函数,就直接执行handler中的静态方法handleMessage
- 第二步:如果Handler中定义了mCallback,那么先去执行mCallBack中的内容。
- 第三步:如果mCallback返回true,说明被mCallback中的handleMessage处理完成不在需要后续的Handler中的handleMessage处理
-第四步:如果mCallback返回false,说明mCallback中的handleMessage没有处理完消息,后续有Handler中的handleMessage继续处理
相对应Message中获取Message对象的方法
- public final Message obtainMessage()
- public final Message obtainMessage(int what)
- public final Message obtainMessage(int what, Object obj)
- public final Message obtainMessage(int what, int arg1, int arg2)
- public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
用Runnable接收消息,这里的Runnable和线程中的Runable不一样只是一个普通的方法,运行在当前线程中。
- public final boolean post(Runnable r)
- public final boolean postAtTime(Runnable r, long uptimeMillis)
- public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
- public final boolean postDelayed(Runnable r, long delayMillis)
- public final boolean postAtFrontOfQueue(Runnable r)
直接发送消息
- public final boolean sendMessage(Message msg)
- public final boolean sendEmptyMessage(int what)
- public final boolean sendEmptyMessageDelayed(int what, long delayMillis)
- public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis)
- public final boolean sendMessageDelayed(Message msg, long delayMillis)
- public boolean sendMessageAtTime(Message msg, long uptimeMillis)
- public final boolean sendMessageAtFrontOfQueue(Message msg)
我叫陆大旭。
一个懂点心理学的无聊程序员大叔。
看完文章无论有没有收获,记得打赏、关注和点赞!