好久没写博客,实在没得写。。。但是项目中用到了Handler去做伪递归用来判断AsyncTask是否finished
就对消息机制有了研究的兴趣,看了好久的SDK sources中的源码
现在写一个消息机制的系列,如有错误或不足,请指正,必修改。
啥叫伪递归呢 就是在Handler对象的handleMessage方法中,如果AsyncTask的getStatus 方法返回的不是
AsyncTask.Status.FINISHED,就sendEmptyMessage给自己。
因为知道Looper处理消息用的是loop方法 这个方法是在当前线程中执行的,也就是同步执行,所以好奇为什么没有出现
ANR,我当时还用一个while 不断的判断AsyncTask的这个状态,但是直接出现了ANR。
后来才知道发送消息之后只会将这个Message插入到MessageQueue中,即单链表插入。并没有立即执行loop方法
如果是主线程的Looper,会在主线程每次循环最后 执行Looper.loop();
虽然这样做并不算是即时的,但是延迟特别小 忽略不计了。。
聊入正题 ----Message
这是消息的载体,要介绍的内容也比较少(当作很久没写东西的过渡吧)
下面看Message的构造,
Message msg = new Message();
这是调用Message无参数的构造方法:
上面写更好的构造一个Message的方法是obtain() ,/** * Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}). */ public Message() { }
大家有没有注意到了这个sPool, 它就是一个Message,如果它不为null,就返回它作为我们的Message,为null就new 一个返回/** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; m.flags = 0; // clear in-use flag sPoolSize--; return m; } } return new Message(); }
那么它在什么时候创建呢,还有为什么有它呢?
我找到了 recycleUchecked() 方法,这个方法在Looper.loop() 中调用,即处理完这个消息后被调用,看loop() 的实现:
/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ 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; Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } ........
msg.target.dispatchMessage(msg); ......... msg.recycleUnchecked(); // 消息通过dispatchMessage处理之后,就去回收它 } }
主要实现在recycleUchecked() 方法:这个方法会回收一个Message 而且这个Message的状态可能是正在使用
而且由于没有权限修饰符,我们直接创建的Message对象调用不了这个方法
/**
* Recycles a Message that may be in-use.
* Used internally by the MessageQueue and Looper when disposing of queued Messages.
*/
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
sPool = this; 这句话表示将调用了recycle方法的Message对象赋值给 sPool,这就解释了为什么用obtain方法更好了
obtain() 会去 使用 被回收了 的Message,这样就避免了创建很多个Message,一种节约资源的做法
obtain() 会去 使用 被回收了 的Message,这样就避免了创建很多个Message,一种节约资源的做法
说起Message的作用,就是MessageQueue中单链表中的一个消息,它能干嘛呢 ?
当Handler的把一条消息发送添加到MessageQueue后,之后当Looper.loop()被调用的时候 就会去处理这个消息 ,
看代码,这是Looper.loop()方法内部
msg.target 是一个Handler 对象,即当初发送它的Handler,现在通过这个target.dispatchMessage()方法将消息又扔回给Handler处理,
看下dispatchMessage(),这个方法在Handler中:
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
这个callback 是Message的一个Runnable对象,如果没传,就不会执行它,最后是调用了handleMessage 方法
当然还有很多细节没说,比如MessageQueue的管理,和Looper , Handler 的创建过程等等
这些以后再写。。。。。。。