Handler消息机制源码解析
handler机制原理
handler发送Message 唤醒Looper器,轮询器开始遍历MessageQueue,轮询取消息,处理消息
学习一项新技术时,可以从源头入手,按流程走,按着代码走向剖析源码。
Message
从API的角度上来看有以下三种,推荐用(2)、(3)种,因为它们本质是从消息池里取消息,
(1)Message msg = new Message();
(2)Message msg = Message.obtain();
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
sPoolSize--;
return m;
}
}
return new Message();
}
方法重载很多,但每个方法本质都会走上面的代码
//
handler.sendMessage(msg);
//handler已经绑定
(3)Message msg = handler.obtainMessage();
msg.sendToTarget();
Looper(轮询器)
* ActivityThread类中初始化,应用程序运行之前执行,main方法如下:
//主线程
public static final void main(String[] args) {
。。。
//轮询器的初始化
Looper.prepareMainLooper();
。。。
//轮询器开始取消息
Looper.loop();
}
*loop方法
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
//没有消息阻塞
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to " + msg.target + " "
+ msg.callback);
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf("Looper", "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycle();
}
}
}
Handler(原名)
Hander的初始化
//程序员写的代码
Handler handler = new Handler(){
public void handleMessage(Message msg){
}
}
//handler的默认构造函数
public Handler() {
。。。
//取出轮询器,轮询取消息
mLooper = Looper.myLooper();
。。。
//消息队列,存放handler发的消息
mQueue = mLooper.mQueue;
mCallback = null;
}
发消息
1、Message类的sendToTarget public void sendToTarget() { 本质还是调用2的发消息方法,target即handler,this即msg。 target.sendMessage(this); }
2、 //1.发消息 handler.sendMessage(msg);//发消息
public final boolean sendMessage(Message msg)
{
//2 sendMessageDelayed 即时消息
return sendMessageDelayed(msg, 0);
}
//2 sendMessageDelayed,参数消息、延时值
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
//3 sendMessageAtTime 加上当前时间来判断
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
//3 sendMessageAtTime
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
//this 就是 handler mQueue 就是从Looper中取出来的消息队列
MessageQueue queue = mQueue;
if (queue != null) {
//handler发消息 把当前的handler对象绑定到Message对象中
msg.target = this;
// 把消息放到消息队列里,按时间排序 ,如果你调用sendMessage(msg),uptimeMillis = 0
//4 enqueueMessage
sent = queue.enqueueMessage(msg, uptimeMillis);
}
。。。
return sent;
}
//4 enqueueMessage
final boolean enqueueMessage(Message msg, long when) {
final boolean needWake;
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
} else if (msg.target == null) {
mQuiting = true;
}
msg.when = when;//Message的发送时间
//Log.d("MessageQueue", "Enqueing: " + msg);
//mMessages 是MessageQueue对象里的属性
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
//msg 发的消息
msg.next = p;
mMessages = msg;
needWake = mBlocked; // new head, might need to wake up
} else {
//消息插入的位置
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
needWake = false; // still waiting on head, no need to wake up
}
}
if (needWake) {
nativeWake(mPtr);//jni
}
return true;
}
取消息
public static final void loop() {
Looper me = myLooper();
//从轮询器中获取消息队列的Handler的queue是同一个消息队列
MessageQueue queue = me.mQueue;
while (true) {
//没有消息阻塞
//从消息队列里取消息头
Message msg = queue.next(); // might block
if (msg != null) {
...
打印日志
。。。
处理消息
msg.target.dispatchMessage(msg);
。。
回收消息,首先清空消息的属性,然后再把消息放到消息池
2.3版本代码功能和结构都有些问题,高版本进行了优化,添加了sPoolSize++
msg.recycle();
}
}
}
处理消息
msg.target.dispatchMessage(msg);
public void dispatchMessage(Message msg) {
if (msg.callback != null) {//runOu......
//处理runOnUithread方法
//1
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//调用handleMessage 主线程
handleMessage(msg);
}
}
//1.
handleCallback(msg);
//2.
private final void handleCallback(Message message) {
message.callback.run();//runnable 跟线程没关系
}
runOnUiThread的原理
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
//1, mHandler.post(action);
mHandler.post(action);
} else {
action.run();
}
}
//1. mHandler.post(action);
public final boolean post(Runnable r)
{
//2.sendMessageDelayed
return sendMessageDelayed(getPostMessage(r), 0);
}
//2.sendMessageDelayed
public final boolean post(Runnable r)
{
3.getPostMessage(r)
return sendMessageDelayed(getPostMessage(r), 0);
}
//3getPostMessage(r)
private final Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}