Android MessageQueen详解

MessageQueen是用来存放消息的,我们具体来看一下MessageQueen的运行机制。

具体描述如下:

Low level class holding the list of messages to be dispatched by a Looper. Messages are not added directly to a MessagreQueen,but rather throw MessageQueen.IdleHandler objects associated with Looper .you can retrieve the MessageQueen for the current thread with Looper.myQueen.

通过上述描述可知,MessageQueen是一个保存消息的低级类,其消息由Looper派发。消息并不是直接添加到MessageQueen当中的,而是通过与Looper对象关联的IdleHandler()添加的。通过调用Looper.myQueen可以获得当前消息所在的队列。

MessageQueen的成员变量有以下几个

Message mMessages;
private final ArrayList<IdleHanlder> mIdleHandlers = new ArrayList<IdleHanlder>();
private IdleHanlder[] mPendingIdleHandlers;
private boolean mQuiting;	
boolean mQuitAllowed = true;
private boolean mBlocked;
private int mPtr;
private native void nativeInit();
private native void nativeDestroy();
private native void nativePollOnce(int ptr,int timeoutMillis);
private native void nativeWake(int ptr);
各个成员变量含义如下:

Message mMessage:一个Message实例,代表消息队列的头Head。

ArrayList<IdleHandler>:存放IdleHandler的数组。

mQuiting:表示当前队列是否处于正在退出的状态。

mQuitAllowed:表示当前队列是否允许退出。

mBlocked:判读队列是否阻塞等待一个非零超时的pollOnce。

mPtr:指向C/C++的指针,主要操作native函数。

上文提到了,Message并不是直接添加到MessageQueen中的,而是通过IdleHandler()接口添加的,那么我们看一下IdleHandler接口的定义

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
	*/
	boolean queueIdle();
}
/** 
     * Add a new IdleHandler to this message queue.  This may be 
     * removed automatically for you by returning false from 
     * IdleHandler queueIdle IdleHandler.queueIdle() when it is 
     * invoked, or explicitly removing it with removeIdleHandler. 
     */ 
public void addIdleHandler(IdleHandler handler){
	if(handler == null){
		throw new NullPointerException("Can't add a null IdleHandler");
	}
	synchronized(this){
		mIdleHandler.add(handler);
	}
}
/** 
     * Remove an IdleHandler from the queue that was previously added 
     * with addIdleHandler.  If the given object is not currently 
     * in the idle list, nothing is done. 
     */ 
public void removeIdleHandler(IdleHandler handler){
	synchronized(this){
		mIdleHandler.remove(handler);
	}
}
当消息队列为空的时候调用IdleHandler接口,并且等待更多的消息。如果返回值为true,则保持当前IdleHandler是活跃的,否则移除当前IdleHandler。如果当前消息队列里面扔有消息,那么在消息执行完之后仍然会调用该接口。

通过addIdleHandler想MessageQueen添加一个IdleHandler,如果调用IdleHandler.queueIdle(),且返回值为false的时候,系统将自动移除该IdleHandler,或者直接调用removeIdleHandler来进行移除。这个方法是线程安全的。

看一个例子

final class myIdle implements MessageQueue.IdleHandler{
	@Override
	public final boolean queueIdle(){
		doSomething();
		return false;
	}
}
当MessageQueen中没有任何消息时,就会执行doSomething(),返回值为false,说明不保留该IdleHandler成员。

MessageQueen的构造方法(在Looper中调用)

MessageQueue(boolean quitAllowed){
	mQuitAllowed = quitAllowed;
	mPtr = nativeInit();
}
MessageQueen的核心方法 next()

Message next() {
        // Return here if the message loop has already quit and been disposed.
        // This can happen if the application tries to restart a looper after quit
        // which is not supported.
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }
 
        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }
 
            nativePollOnce(ptr, nextPollTimeoutMillis);
 
            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }
 
                // Process the quit message now that all pending messages have been handled.
                if (mQuitting) {
                    dispose();
                    return null;
                }
 
                // If first time idle, then get the number of idlers to run.
                // Idle handles only run if the queue is empty or if the first message
                // in the queue (possibly a barrier) is due to be handled in the future.
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                if (pendingIdleHandlerCount <= 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }
 
                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }
 
            // Run the idle handlers.
            // We only ever reach this code block during the first iteration.
            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler
 
                boolean keep = false;
                try {
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }
 
                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }
 
            // Reset the idle handler count to 0 so we do not run them again.
            pendingIdleHandlerCount = 0;
 
            // While calling an idle handler, a new message could have been delivered
            // so go back and look again for a pending message without waiting.
            nextPollTimeoutMillis = 0;
        }
    }
简单的说,这个函数就是从从头Head取出下一个Message,如果队列中没有message了,那么则可以取处理IdleHandler接口。当队列中没有消息或者消息指定了等待时间,那么线程会进入等待状态。

函数中有两个变量
int pendingIdleHandlerCount = -1;空闲的IdleHandler个数,只有在第一次迭代的时候为-1。

int nextPollTimeoutMillis = 0;下一轮等待时间,如果当前消息队列中没哟消息,需要等待的时间。

如果等待时间不为零,执行flush pending command,刷新等待时间。然后执行nativePollOnce(ptr, nextPollTimeoutMillis);其功能是查询消息队列中有没有消息。如果消息为空,那么nextPollTimeoutMillis=-1,接着等待消息,如果不为空,那么就处理这个消息。当我们设置的等待时间到了,将msg从Message中取出来并返回msg,如果没有返回,则说明没有消息需要处理,既然没有消息需要处理,检查以下是否要退出队列,如果退出返回null,否则那么就可以处理IdleHandler,处理完IdleHandler后将nextPollTimeoutMillis设为0(因为在处理IdleHandler的时候可能来消息),重新检测消息。

插入操作

boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }
 
        synchronized (this) {
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }
 
            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                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()) {
                        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;
    } 

如果msg正在使用或者msg对应的Handler为空或者不予许退出,则报异常。如果正在退出,则不允许进行插入操作,否则报异常。正常的插入操作类似于链表。当when=0或者when<p.when时插入表头。

删除

void removeMessages(Handler h, int what, Object object) {
       if (h == null) {
           return;
       }
 
       synchronized (this) {
           Message p = mMessages;
 
           // Remove all messages at front.
           while (p != null && p.target == h && p.what == what
                  && (object == null || p.obj == object)) {
               Message n = p.next;
               mMessages = n;
               p.recycleUnchecked();
               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)) {
                       Message nn = n.next;
                       n.recycleUnchecked();
                       p.next = nn;
                       continue;
                   }
               }
               p = n;
           }
       }
   }
 
   void removeMessages(Handler h, Runnable r, Object object) {
       if (h == null || 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.recycleUnchecked();
               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.recycleUnchecked();
                       p.next = nn;
                       continue;
                   }
               }
               p = n;
           }
       }
   }
 
   void removeCallbacksAndMessages(Handler h, Object object) {
       if (h == null) {
           return;
       }
 
       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.recycleUnchecked();
               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.recycleUnchecked();
                       p.next = nn;
                       continue;
                   }
               }
               p = n;
           }
       }
   } 

quit()方法

void quit(boolean safe) {
        if (!mQuitAllowed) {
            throw new IllegalStateException("Main thread not allowed to quit.");
        }
 
        synchronized (this) {
            if (mQuitting) {
                return;
            }
            mQuitting = true;
 
            if (safe) {
                removeAllFutureMessagesLocked();
            } else {
                removeAllMessagesLocked();
            }
 
            // We can assume mPtr != 0 because mQuitting was previously false.
            nativeWake(mPtr);
        }
    }






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值