大三了,老想自己写点市面上没有的东西,这些天在尝试写一个可以用鼠标操作手机的android应用,前段时间苦于找不到能在屏幕上产生触摸事件的方法,找了N久,发现一个Instrumentation类,觉得靠谱,就拿过来试一试。用的时候发现要在不同的线程里使用,于是我想是不是做个像android消息队列的结构,无信息要处理的时候线程等待,一旦有信息就立刻处理。
但是连猪跑都没见过,自己写一个谈何容易?想起在博客上看到的名言:“read the fucking source code!”一股“老子要读源码了”的屌丝优越感油然而生,于是对android的MessageQueue类做了下面的翻译和注释,翻译的过程中发现网上已经有了相似的东西,决知要躬行,最后还是自己又逐行读了一遍,其中不乏不懂之处,真心希望高手发现欠妥之处或看的我的疑问后不吝赐教!
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.finetu.bo;
import java.util.ArrayList;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.util.AndroidRuntimeException;
import android.util.Config;
import android.util.Log;
/**
* Low-level class holding the list of messages to be dispatched by a
* {@link Looper}. Messages are not added directly to a MessageQueue,
* but rather through {@link Handler} objects associated with the Looper.
*
* <p>You can retrieve the MessageQueue for the current thread with
* {@link Looper#myQueue() Looper.myQueue()}.
*
* 底层类,用于维护一个message的列表,被一个Looper对象使用。Message对象并不直接加进MessageQueue中,
* 但可以认为是通过Handler对象与Looper关联。
*
* 调用Looper.mayQueue()可以得到当前线程的Message对象。
*/
public class MessageQueueOfAndroid {
Message mMessages;
//handler对象列表,个人理解为观察者列表
private final ArrayList mIdleHandlers = new ArrayList();
private boolean mQuiting = false;
boolean mQuitAllowed = true;
/**
* Callback interface for discovering when a thread is going to block
* waiting for more messages.
*
* 当进程将要等待更多Message而挂起时的回调接口。
*/
public static interface IdleHandler {
/**
* Called when the message queue has run out of messages and will now
* wait for more. Return true to keep your idle handler active, false
* to have it removed. This may be called if there are still messages
* pending in the queue, but they are all scheduled to be dispatched
* after the current time.
*
* 当消息队列处理完所有的message需要等待更多message时调用本方法。当需要保持空闲Handler(这里的所
* 谓空闲Handler个人理解为做为观察者的Handler)活动状态时返回true,反之要移除时返回false。这个方
* 法有被调用时在消息队列中可能仍然有待处理的消息,但这些消息会在下一时刻被处理。
*/
boolean queueIdle();
}
/**
* Add a new {@link IdleHandler} to this message queue. This may be
* removed automatically for you by returning false from
* {@link IdleHandler#queueIdle IdleHandler.queueIdle()} when it is
* invoked, or explicitly removing it with {@link #removeIdleHandler}.
*
* <p>This method is safe to call from any thread.
*
* @param handler The IdleHandler to be added.
*
* 添加一个新的绑定当前消息队列的Handler对象。该对象被调用后可能会因为IdleHandler.queueIdle()方法返
* 回值为false而被自动移除,或者被removeIdlerHandler()方法显式移除。
*
* 任何线程调用该方法都是安全的。
*
* 参数:handler 要添加的Handler对象。
*/
public final void addIdleHandler(IdleHandler handler) {
if (handler == null) {
throw new NullPointerException("Can't add a null IdleHandler");
}
synchronized (this) {
//向Handler列表中添加Handler对象 。
mIdleHandlers.add(handler);
}
}
/**
* Remove an {@link IdleHandler} from the queue that was previously added
* with {@link #addIdleHandler}. If the given object is not currently
* in the idle list, nothing is done.
*
* @param handler The IdleHandler to be removed.
*
* 从加入了Handler的队列中删除Handler对象,如果参数中的对象在列表中未找到,则什么也不做。
*
*/
public final void removeIdleHandler(IdleHandler handler) {
synchronized (this) {
mIdleHandlers.remove(handler);
}
}
//空构造函数
MessageQueueOfAndroid() {
}
/**
*
*/
final Message next() {
boolean tryIdle = true;
while (true) {
long now;//记录当前时间
Object[] idlers = null;//Handler列表
// Try to retrieve the next message, returning if found.
//尝试取出下一条消息,如果成功则返回
synchronized (this) {
now = SystemClock.uptimeMillis();//把系统时间赋给now
Message msg = pullNextLocked(now);//从当前的消息队列中拿出当前允许拿出的一个Message对象
if (msg != null) return msg;//对象不为空,返回
if (tryIdle && mIdleHandlers.size() > 0) {//拿到Handler的数组
idlers = mIdleHandlers.toArray();
}
}
// There was no message so we are going to wait... but first,
// if there are any idle handlers let them know.
//没有取出下一条消息,需要等待,但是首先,如果Handler数组中有Handler对象,则通知这些对象,
boolean didIdle = false;//标记是否执行过Handler回调的标志位
if (idlers != null) {
for (Object idler : idlers) {
boolean keep = false;
try {
didIdle = true;//已有Handler调用了自己的queueIdle()方法,记录状态。
//消息队列需要等待,此处一次调用Handler对象的queueIdle()方法,
//使得需要移出的Handler被移除,无需移出的被保存
keep = ((IdleHandler)idler).queueIdle();
} catch (Throwable t) {
Log.wtf("MessageQueue", "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);//移除Handler的操作
}
}
}
}
// While calling an idle handler, a new message could have been
// delivered... so go back and look again for a pending message.
//当有Handler调用了回调函数时,可能恰好有一个消息加入了消息队列,所以需要让最上层的while循环
//重新循环一遍看有没有就绪的Messaged对象。(此处笔者不明白为何直接continue就可以做到这种功能,
//因为对于有无新的Message,didIdle应该会有不同的状态,单位和这两种不同的状态可以代表有无Message对象,笔者不明白)
if (didIdle) {
tryIdle = false;
continue;
}
synchronized (this) {
// No messages, nobody to tell about it... time to wait!
//没有消息了,此时已经不需要通知任何Handler对象,队列开始等待
try {
if (mMessages != null) {//消息队列非空,说明有消息在一段可预知的时间后可以获取到,此时只需等待这一段有限的时间即可
if (mMessages.when-now > 0) {
Binder.flushPendingCommands();//Binder操作,刷新什么不知道--"
this.wait(mMessages.when-now);//等待已知的有限长时间
}
} else {//否则,不知道何时会有新的Message可以拿到
Binder.flushPendingCommands();
this.wait();//持续等待
}
}
catch (InterruptedException e) {
}
}
}
}
/**
* 在message链表中取出当前时间下可取出的下一个Message对象,在一些特殊情况下,Message可以设置delay,来人
* 为延迟一段时间,这时不能立即取出队头的message对象,此处直接返回null。
*/
final Message pullNextLocked(long now) {
Message msg = mMessages;
if (msg != null) {
if (now >= msg.when) {
mMessages = msg.next;
if (Config.LOGV) Log.v(
"MessageQueue", "Returning message: " + msg);
return msg;
}
}
return null;
}
/**通过when即时间,在message链表中插入新的message对象,参数msg.target==null作为执行quit操作的标识,
* 插入前将msg的when属性用参数when赋值,若原本的链表为空,或when是最小的,则加在链表头,否则循环,找到一个合适
* 的位置插入msg,最后返回true。
*/
final boolean enqueueMessage(Message msg, long when) {
if (msg.when != 0) {
throw new AndroidRuntimeException(msg
+ " This message is already in use.");
}
if (msg.target == null && !mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit");
}
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;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
this.notify();
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
this.notify();
}
}
return true;
}
//重写的删除消息方法
final boolean removeMessages(Handler h, int what, Object object,
boolean doRemove) {
synchronized (this) {
Message p = mMessages;
boolean found = false;
// Remove all messages at front.
while (p != null && p.target == h && p.what == what
&& (object == null || p.obj == object)) {
if (!doRemove) return true;
found = true;
Message n = p.next;
mMessages = n;
p.recycle();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && n.what == what
&& (object == null || n.obj == object)) {
if (!doRemove) return true;
found = true;
Message nn = n.next;
n.recycle();
p.next = nn;
continue;
}
}
p = n;
}
return found;
}
}
//重写的删除消息方法
final void removeMessages(Handler h, Runnable r, Object object) {
if (r == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
while (p != null && p.target == h && p.callback == r
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycle();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && n.callback == r
&& (object == null || n.obj == object)) {
Message nn = n.next;
n.recycle();
p.next = nn;
continue;
}
}
p = n;
}
}
}
//删除所有的Handler和Message
final void removeCallbacksAndMessages(Handler h, Object object) {
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
while (p != null && p.target == h
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycle();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && (object == null || n.obj == object)) {
Message nn = n.next;
n.recycle();
p.next = nn;
continue;
}
}
p = n;
}
}
}
/*
private void dumpQueue_l()
{
Message p = mMessages;
System.out.println(this + " queue is:");
while (p != null) {
System.out.println(" " + p);
p = p.next;
}
}
*/
//把控制权交给下一个等待的线程(对线程理解不深,仅供参考)
void poke()
{
synchronized (this) {
this.notify();
}
}
}