先看一下消息机制的原理图:
源码相关调用:
相关源码说明
Message.java
public int what;//标识(id)
public int arg1;//保存int数据
public int arg2;//保存int数据
public Object obj;//保存任意数据
long when;//记录应该被处理的时间值
Handler target;//用来处理消息的Handler对象,就是发送消息的那个
Handler:发送消息,处理消息,移除消息
1. 发消息
public final boolean sendMessage (Message msg){
return this.sendMessageDelayed(msg, 0L);//发送延时消息,延时为0
}
2. 发空消息,默认延时为0
public final boolean sendEmptyMessage ( int what){
return this.sendEmptyMessageDelayed(what, 0L);
}
3. 发空消息,延时为delayMillis
public final boolean sendEmptyMessageDelayed ( int what, long delayMillis){
Message msg = Message.obtain();
msg.what = what;
return this.sendMessageDelayed(msg, delayMillis);//发送延时消息,,延时为delayMillis
}
4. 发消息,延时delayMillis,计算出消息应该被处理时间when = 当前时间 + 延时
public final boolean sendMessageDelayed (Message msg,long delayMillis){
if (delayMillis < 0L) {
delayMillis = 0L;
}
return this.sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
5.发消息,最终调用消息队列保存消息对象
public boolean sendMessageAtTime (Message msg,long uptimeMillis){
MessageQueue queue = this.mQueue;
......
return this.enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;//保存发送消息的Handler(Message.java 的target 赋值的地方)
......
return queue.enqueueMessage(msg, uptimeMillis);//调用消息队列保存消息对象
}
6.移除消息
public final void removeMessages(int what) {
this.mQueue.removeMessages(this, what, (Object)null);//调用消息队列移除它内部的指定what消息
}
7.处理消息的回调方法
public void handleMessage(Message msg) {
}
8.
public void dispatchMessage(Message msg) {
if(msg.callback != null) {//消息自己可以处理,让消息自己处理
handleCallback(msg);
} else {
//如果Handler对象中有回调监听,调用回调器来处理消息
if(this.mCallback != null && this.mCallback.handleMessage(msg)) {
return;
}
this.handleMessage(msg);//让Handler的handleMessage来处理。
}
}
MessageQueue:存储消息,以Message的when排序
1.将Message添加到队列中
boolean enqueueMessage(Message msg, long when) {
.....
msg.when = when;//执行消息应该被处理的时间(Handler中发消息,延时delayMillis,计算出的时间when = 当前时间 + 延时)
if (p != null && when != 0L && when >= p.when) {//将当前消息保存到消息队列中的一个合适的位置
needWake = this.mBlocked && p.target == null && msg.isAsynchronous();
while (true) {
Message prev = p;
p = p.next;
if (p == null || when < p.when) {
msg.next = p;
prev.next = msg;
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
} else {//消息队列为空的或者没有消息的when比新插入消息的when小,则该消息插入到第一个位置
msg.next = p;
this.mMessages = msg;
needWake = this.mBlocked;
} //最终得到的结果是:消息队列是按when来排序的。
nativeWake(this.mPtr);//通过本地方法实现对处理等待状态的底层线程
}
2.取出一个合适的Message对象,可能不会立即返回
Message next() {
.....
this.nativePollOnce(ptr, nextPollTimeoutMillis);//本地方法,会导致可能处理等待状态,但不会阻塞主线程
.....
Message msg = this.mMessages;//取出消息队列中的第一个消息
.....
return msg;//返回
}
Looper.java
1. 核心方法
public static void loop() {
Looper me = myLooper();//得到Looper对象
while(true) {//无限循环
Message msg = queue.next();//从消息队列中取出消息
msg.target.dispatchMessage(msg); // 调用Handler去分发并处理消息
msg.recycleUnchecked();//回收利用Message
}
}