在平常開發中主要做用於兩方面:
一、在UI線程進行耗時操做時,將耗時操做拋到子線程進行處理,不然容易ANR。
二、在子線程中刷新UI。
java
Handler、Looper、MessageQueue 和 Message 是組成Handler通訊機制的基礎。android
Handler的使用基本如如下代碼所示,或者繼承Handler重寫handleMessage,處理不一樣what標識的Message。不是本文討論的重點,不作過多敘述。設計模式
//建立子線程Handler
HandlerThread mHandlerThread = new HandlerThread("daqi");
mHandlerThread.start();
Handler mHandler = new Handler(mHandlerThread.getLooper());
//建立Message
Message message = mHandler.obtainMessage();
//發送Message
mHandler.sendMessage(message);
//post
mHandler.post(new Runnable() {
@Override
public void run() {
}
});
複製代碼
建立Handler,並綁定Looper -> Handler發送Message -> Message存儲到Looper的MessageQueue中 -> Looper在MessageQueue中拿取頂部Message -> 將Message發送給目標Handlerbash
Handler、Looper、MessageQueue 和 Message的關係:
異步
帶着問題看源碼:
一、Looper如何確保線程中只有一個單例。
async
二、爲何建議使用Handler#obtainMessage()獲取Message對象,而不是直接new。
ide
三、Handler的sendMessage() 和 post()有什麼區別。
函數
四、Looper如何管理Message隊列(即前後發送不一樣延遲時間的Message,Message隊列如何排序)。
oop
五、removeCallbacks、removeMessages 和 removeCallbacksAndMessages都移除了什麼。
源碼分析
Handler在建立時,默認構造方法會綁定當前線程。因此咱們選擇先從Handler的默認構造方法看起。
#Handler.java
//無參構造函數
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
//....
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
}
複製代碼
建立Handler對象時,無參構造函數會獲取當前線程的Looper並獲取到其MessageQueue存儲到Handler自身變量中。
但咱們也觀察到,若是沒有Looper的Thread中建立,會拋出RuntimeException,並告訴你該線程無Looper。
從Handler的默認構造方法中得知,在建立Handler前,須要先在當前線程中建立Looper對象和MessageQueue對象。而建立Looper對象和MessageQueue對象只須要調用以下方法:
Looper.prepare();
Looper.loop();
複製代碼
prepare的意思是準備,便可以猜想Looper是在Looper#prepare()中初始化的,因此先從Looper#prepare()的源碼看起:
#Looper.java
//主要用於做爲存儲的Looper實例的key。
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//ThreadLocal#get()獲取當前線程的looper對象
if (sThreadLocal.get() != null) {
//若是Looper已經實例化完,則會拋出異常
throw new RuntimeException("Only one Looper may be created per thread");
}
//若是以前當前線程沒有初始化過Looper,則建立Looper並添加到sThreadLocal中
sThreadLocal.set(new Looper(quitAllowed));
}
複製代碼
咱們發現Looper#prepare()調用重載函數Looper#prepare(boolean)。在這方法中,Looper會被初始化。查看Looper私有構造函數,發現Looper會初始化MessageQueue並存儲當前線程。
而Looper被初始化是有一個前提的,即sThreadLocal.get() == null。不然會拋出RuntimeException,並告訴你該線程只能建立一個Looper對象。
sThreadLocal是Looper類中定義的一個靜態ThreadLocal常量。繼續查看ThreadLocal#get()和ThreadLocal#set()方法。
#ThreadLocal.java
public T get() {
//獲取當前線程
Thread t = Thread.currentThread();
//線程中存在一個ThreadLocal.ThreadLocalMap類型的變量
//根據當前線程thread獲取到對應的ThreadLocal.ThreadLocalMap變量。
ThreadLocalMap map = getMap(t);
if (map != null) {
//this表示Looper類中的靜態ThreadLocal常量sThreadLocal
//由於sThreadLocal是靜態常量,做爲「key」,確保變量爲單例。
//根據sThreadLocal獲取到對應的ThreadLocalMap.Entry值。
ThreadLocalMap.Entry e = mapgetEntry(this);
if (e != null) {
//從ThreadLocalMap.Entry中獲取到對應的Looper,
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
public void set(T value) {
//獲取當前線程
Thread t = Thread.currentThread();
//線程中存在一個ThreadLocal.ThreadLocalMap類型的變量
//根據當前線程thread獲取到對應的ThreadLocal.ThreadLocalMap變量。
ThreadLocalMap map = getMap(t);
if (map != null)
//將sThreadLocal做爲「key」,Looper實例做爲「value」存儲到ThreadLocal.ThreadLocalMap中
map.set(this, value);
else
//建立Map並存儲值
createMap(t, value);
}
void createMap(Thread t, T firstValue) {
//建立ThreadLocalMap,構造方法中傳入第一次存儲的鍵值對,並賦值到當前線程的threadLocals變量中。
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
複製代碼
能夠觀察到,get()和set()方法獲取當前線程中的ThreadLocal.ThreadLocalMap變量。再將Looper#sThreadLocal做爲key,存儲或獲取對應的value,而value就是當前線程建立的Looper實例。
get()時是根據當前線程獲取的Looper單例,再結合Looper#prepare(boolean),能夠知道單個線程只會生成Looper單個實例。
問題1:Looper如何確保線程中只有一個單例。
回答:將Looper構造方法私有化。經過Looper的靜態方法,確保只建立一次Looper對象,再將靜態常量sThreadLocal做爲key,Looper對象做爲value,存儲到當前線程的ThreadLocal.ThreadLocalMap變量中。
查看完Looper初始化的流程,再看看Looper#loop()的源碼
#Looper.java
public static void loop() {
//獲取當前線程的Looper
final Looper me = myLooper();
//若是Looper沒有初始化,則拋異常
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//從Looper實例中獲取當前線程的MessageQueue
final MessageQueue queue = me.mQueue;
//消息循環(經過for循環)
for (;;) {
//一、從消息隊列中獲取消息
Message msg = queue.next();
if (msg == null) {
//沒有消息代表消息隊列正在退出。
return;
}
//省略代碼.....
//二、將Message發送給其標記的targetHandler
msg.target.dispatchMessage(msg);
//省略代碼.....
//三、回收可繼續使用的Message
msg.recycleUnchecked();
}
}
複製代碼
Looper#loop()主要作3件事:
一、不斷從MessageQueue中取出Message,若暫無Message,則無限等待。
二、將Message發送給目標Handler進行處理。
三、回收Message對象。
但發現有一種狀況,當next獲取到的Message爲空時,則會退出Looper#loop()方法,即意味着消息循環結束。那何時MessageQueue#next()返回null?
#MessageQueue.java
Message next() {
//若是消息循環已經退出並處理掉,請返回此處。
//若是應用程序嘗試在退出後從新啓動looper,則可能會發生這種狀況。
//即MessageQueue調用了quit()方法,再次調用Looper#looper()方法時。
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
//決定消息隊列中消息出隊的等待時間 or 標記爲無限等待狀態
int nextPollTimeoutMillis = 0;
for (;;) {
//.....
// nativePollOnce方法在native層方法。
//如果nextPollTimeoutMillis爲-1,則無限等待,此時消息隊列處於等待狀態。
//如果nextPollTimeoutMillis爲0,則無需等待當即返回。
//若nextPollTimeoutMillis>0,最長阻塞nextPollTimeoutMillis毫秒(超時),若是期間有程序喚醒會當即返回。
nativePollOnce(ptr, nextPollTimeoutMillis);
//嘗試檢索下一條消息。 若是找到則返回。
synchronized (this) {
//獲取從開機到如今的毫秒數
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
//獲取MessageQueue中的頂層Message
Message msg = mMessages;
//.....
if (msg != null) {
//若是massage的時間大於當前時間
//Message的when = Handler發送Message1時的開機時間SystemClock.uptimeMillis() + Message自身的延遲時間
if (now < msg.when) {
// 下一條消息還沒有就緒。 設置該Message的等待時間以在準備就緒時喚醒。
//將msg.when - now(當前開機時間) 獲得該Message須要多久以後發送。
//則刷新nextPollTimeoutMillis的值,設置等待時間。
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {//不然立刻發送Message
//只有當msg.target == null時,prevMsg纔會賦值。
//聽從Handler#obtainMessage()則通常不爲空,此狀況不考慮。
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
//剛開始時prevMsg爲空
//則mMessages(頂層Message)指向當前頂層Message的下一個Message
mMessages = msg.next;
}
//將返回的Message的下一個Message引用置空。
msg.next = null;
msg.markInUse();
return msg;
}
} else {
//若是MessageQueue中沒有Message,則會將nextPollTimeoutMillis重置爲-1,繼續等待
nextPollTimeoutMillis = -1;
}
//.....
}
//.....
}
}
複製代碼
從源碼開頭得知,當MessageQueue退出時,MessageQueue#next()則會返回Message對象爲空,從而關閉消息循環。
MessageQueue#next()主要進行等待操做和返回Message操做。而等待操做分兩種狀況:
一、MessageQueue隊列中無Message,則進行無限等待操做。
二、當Message還沒處處理時間時,則計算該Message還須要等待的時間,進行相應時間的延遲。
查看Handler如何處理Message:
#Handler.java
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//若是Message的callback不爲空,則將消息交由Message的callback處理
handleCallback(msg);
} else {
if (mCallback != null) {
//若是Handler的callback不爲空,則將消息交由Handler的callback處理
if (mCallback.handleMessage(msg)) {
return;
}
}
//最後才交由Handler的handleMessage()方法處理。
handleMessage(msg);
}
}
複製代碼
Handler#dispatchMessage()主要做用時將Message分發處理。
當該Message對象的callback爲空,目標Handler的callback也爲空時,才輪到handleMessage()進行消息處理。
建立Message對象時,咱們通常會調用Handler#obtainMessage()獲取Message對象,而不是直接new。先從Handler#obtainMessage()開始查看起因:
#Handler.java
public final Message obtainMessage(){
return Message.obtain(this);
}
複製代碼複製代碼
#Message.java
//Message鏈表,sPool是表頭
private static Message sPool;
//記錄當前鏈表中的數量
private static int sPoolSize = 0;
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
public static Message obtain() {
//加鎖
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
//鏈表表頭指向其下一個對象,即將表頭從鏈表中取出
sPool = m.next;
//重置返回的Message的一些信息
m.next = null;
m.flags = 0; // clear in-use flag
//鏈表數量減一
sPoolSize--;
return m;
}
}
//若是鏈表表頭爲空,則new Message對象。
return new Message();
}
複製代碼複製代碼
Message#obtain(Handler)調用了重載方法Message#obtain()獲取到Message對象並將Message的目標設置爲調用Handler#obtainMessage()的Message。
Message對象中擁有一個Message類型的next對象,可經過next屬性連成一個Message鏈表。Message中維繫着一個靜態Message鏈表,當鏈表不爲空時,取出表頭的Message進行返回,不然new一個Message對象。
以前查看Looper#loop()源碼時獲知,Looper#loop()最後會調用Message#recycleUnchecked(),將Message進行回收。
#Message.java
//Message鏈表最大存儲數量值
private static final int MAX_POOL_SIZE = 50;
void recycleUnchecked() {
//將消息保留在循環對象池中時將其標記爲正在使用。
//清除全部其餘細節。
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表明的是該須要回收的Message自身的next對象
//將自身的next指向原表頭,
next = sPool;
//自身替換爲表頭,則經過表頭的加減實現該Message鏈表的增長和刪除。
sPool = this;
//鏈表存儲數量加一
sPoolSize++;
}
}
}
複製代碼複製代碼
Message#recycleUnchecked()將Message的參數重置,並判斷當前Messag鏈表存儲的數量是否小於最大存儲值,若小於最大存儲值,則將該Message存儲到鏈表中,重複使用。
Message經過對鏈表表頭的增刪操做來進行鏈表的增減。
問題2:爲何建議使用Handler#obtainMessage()獲取Message對象,而不是直接new。
回答:Message的回收機制實際上是享元設計模式的實現,Message對象存在須要反覆、較大規模建立的狀況,使用享元設計模式能夠減小建立對象的數量,以減小內存佔用和提升性能。
總結:
Message對象中擁有一個Message類型的next對象,可經過next屬性連成一個Message鏈表。
Message類中維繫着個靜態Message鏈表,並標記其存儲的數量值。
調用Handler#obtainMessage()或Message#obtain()方法時,嘗試從該靜態鏈表中獲取循環再用的Message對象,不然new Message對象返回出去。
當Message被Handler處理完後,Looper對象會調用Message#recycleUnchecked()將Message進行回收,並存儲到靜態Message鏈表中。
咱們都知道,Handler能夠經過sendMessage和post進行消息的發送,這兩種方法到底有什麼區別?先從sendMessage看起:
#Handler.java
public final boolean sendMessage(Message msg){
//發送一個0延遲的message
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis){
//延遲值不能小於0
if (delayMillis < 0) {
delayMillis = 0;
}
//將延遲的時間和開機時間相加
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
//獲取Handler建立時存儲的當前線程的MessageQueue
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//將Message的目標TargetHandler設置爲當前Handler
//若是經過Handler#obtainMessage()獲取的Message早設置了TargetHandler爲當前Handler,通常是新new的Message才爲空。
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
複製代碼複製代碼
一路都是方法的嵌套,其中最關鍵的就是在傳遞給sendMessageAtTime()方法前,將延時時間和手機開機時間相加,獲得Message對象的"執行時間"。
在繼續查看MessageQueue#enqueueMessage():
#MessageQueue.java
//標記MessageQueue#next()的nativePollOnce()是否以 非零超時等待(無限等待)被阻止。
private boolean mBlocked;
boolean enqueueMessage(Message msg, long when) {
//.....
synchronized (this) {
//...
msg.markInUse();
//將延遲時間和開機時間相加獲得的時間值存儲到message的when變量中。
msg.when = when;
//獲取鏈表表頭的Message
Message p = mMessages;
boolean needWake;
//當表頭爲空時,或者本次發送的Message對象「執行時間」比表頭的時間要小時
if (p == null || when == 0 || when < p.when) {
//將本次發送的Message存儲到表頭前面,將next屬性指向原鏈表表頭
msg.next = p;
//刷新MessageQueue中指向表頭的變量
mMessages = msg;
needWake = mBlocked;
} else {
//一般不須要喚醒事件隊列,除非隊列的頭部有屏障,而且消息是隊列中最先的異步消息。
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
//開啓循環,便利MessageQueue的Message鏈表
for (;;) {
//prev先指向原表頭,後續循環中,不斷指向下一個元素
prev = p;
//p指向下一個元素
p = p.next;
//若是p== null,表示到鏈表的尾部
//或者本次發送的Message對象的「執行時間」when比下一個元素的「執行時間」要短
if (p == null || when < p.when) {
//推出循環
break;
}
//...
}
//此時,prev指向的Message對象的when 比本次發送的Message對象msg的when小,即「執行時間」比它小。
//p可能爲空,即鏈表尾;或者p指向的Message對象的when比 比本次發送的Message對象msg的when大,即「執行時間」比它大。
// 便可能存在 prev.when < msg.when <p.when 或 prev.when < msg.when
//將msg的next變量指向p所指的對象
msg.next = p;
//prev所指向的message對象的next變量指向msg
prev.next = msg;
}
//判斷是否須要喚醒以前在MessageQueue#next()中「陷入沉睡」的nativePollOnce()方法。
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
複製代碼複製代碼
MessageQueue#enqueueMessage()主要做用是:
一、依據msg.when的大小,按從小到大的順序,將msg插入到MessageQueue的Message鏈表中。
二、對於立刻執行的message,直接喚醒,中止nativePollOnce()的無限等待,讓MessageQueue#next返回繼續執行,從Message鏈表中取出Message,交由Looper對象進行處理。
模擬狀況:
同時發送延遲400毫秒的Message對象 和 延遲300毫秒的Message對象;
100毫秒後,再發送延遲延遲250毫秒的Message對象;
情景分析:
同時發送兩個分別延遲400和延遲300的Message對象,此時系統開機時間 time = SystemClock.uptimeMillis();
延遲400的Message對象:msg400, msg400 .when = time + 400;。
首先進入MessageQueue的Message鏈表,因爲本來Message鏈表爲空,p == null,表頭mMessages指 msg400
延遲300的Message對象:msg300, msg300.when = time + 300;。
進入if(p == null || when == 0 || when < p.when)語句 ,p != null ,msg300.when < msg400.when , msg300.next 指向 msg400,鏈表表頭指向msg300;
100毫秒後,發送延遲延遲250毫秒的Message對象。此時系統開機時間 time2 = SystemClock.uptimeMillis(),相對time 大了100毫秒,即time2 = time + 100毫秒。
延遲250的Message對象:msg250, msg250.when = time2 + 250, 即msg250.when = time + 350。
進入if(p == null || when == 0 || when < p.when)語句,語句不成立,進入遍歷Message鏈表的for循環。when < p.when判斷中,msg250.when > msg300.when,循環繼續。msg250.when < msg400.when,跳出循環。執行msg.next = p; 和 prev.next = msg;兩個語句,即msg250.next = msg400,msg300.next = msg250。
問題4:Looper如何管理Message隊列(即前後發送不一樣延遲時間的Message,Message隊列如何排序)。
回答:Message經過SystemClock.uptimeMillis() + 延遲時間給自身when賦值,經過值的大小做爲執行順序。SystemClock.uptimeMillis() 不根據當前時區的時間變化而變化,只會因開關機而被重置,不然始終自增。
因此能夠根據當前的SystemClock.uptimeMillis() 與Message對象的when對比,知道立刻執行仍是延遲多少秒後才執行。
轉換到Handler#ost()的源碼:
#Handler.java
public final boolean post(Runnable r){
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//若是Message的callback不爲空,則將消息交由Message的callback處理
handleCallback(msg);
} else {
if (mCallback != null) {
//若是Handler的callback不爲空,則將消息交由Handler的callback處理
if (mCallback.handleMessage(msg)) {
return;
}
}
//最後才交由Handler的handleMessage()方法處理。
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
//只是調用callback的run()方法。
message.callback.run();
}
複製代碼複製代碼
post()傳遞的Runnable對象會被套上一層Message外殼,最後走和sendMessage()同樣的路線。
Runnable對象將存儲在Message對象的callback對象中。在Handler處理Message時,因爲callback對象不爲空,調用Handler#handleCallback()對Runnable對象調用run()方法,實現Message的處理。
問題3:Handler的sendMessage() 和 post()有什麼區別。
回答:post()會將Runnable對象轉換爲Message對象,並把Runnable對象存儲在Message對象的callback中,而後繼續走sendMessage()的路線。
在Handler處理Message對象時,post()方法產生的Message對象中callback不爲空,由Handler調用Runnable對象的run方法,不會調用handleMessage();
#Handler.java
public final void removeMessages(int what) {
mQueue.removeMessages(this, what, null);
}
public final void removeCallbacks(Runnable r){
mQueue.removeMessages(this, r, null);
}
public final void removeMessages(int what, Object object) {
mQueue.removeMessages(this, what, object);
}
public final void removeCallbacks(Runnable r, Object token){
mQueue.removeMessages(this, r, token);
}
複製代碼複製代碼
#MessageQueue.java
void removeMessages(Handler h, int what, Object object) {
//...
synchronized (this) {
//獲取Message鏈表表頭
Message p = mMessages;
//從頭開始尋找,尋找第一個不符合條件的Message。分兩種狀況:
//一、鏈表表頭直接不符合移除條件,即第一個不符合條件的Message爲鏈表表頭,推出循環。
//二、鏈表符合移除條件,將鏈表表頭指向原表頭的下一個Message,並回收原鏈表表頭。新的鏈表表頭繼續進行判斷,直到出現不符合移除條件的Message出現。
//最後鏈表表頭mMessages 和 p都指向第一個不符合條件的Message,前面符合移除條件的Message已被移除。
while (p != null && p.target == h && p.what == what
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
//從第一個不符合條件的Message對象開始,迭代尋找其下一個Message是否符合移除條件。
while (p != null) {
Message n = p.next;
if (n != null) {
//判斷是否符合移除條件
if (n.target == h && n.what == what
&& (object == null || n.obj == object)) {
//獲取p.next().next()的Message對象,即下下個對象。
Message nn = n.next;
//符合條件的回收
n.recycleUnchecked();
//將本來的下下個Message轉移到next對象中,即轉移到下一個Message的位置上。
p.next = nn;
continue;
}
}
//n == null,表示到鏈尾了,則 p == null,while循環結束。
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;
}
}
}
複製代碼複製代碼
removeMessages(Handler, int, Object) 根據Message中的what進行刷選移除對象。
removeMessages(Handler, Runnable,Object)則根據相同的Runnable對象進行刷選移除。
二者的都是走相同的移除對象流程,只是其中的一種刷選條件有所不一樣,what針對的是Handler#sendMessage()發送的Message,Runnable針對的是Handler#post()發送的Message。
Handler#removeCallbacksAndMessages()則移除這兩種刷選條件,針對全部Message。
問題5:removeCallbacks、removeMessages 和 removeCallbacksAndMessages都移除了什麼
回答:removeCallbacks、removeMessages 和 removeCallbacksAndMessages 在待處理的Message鏈表中,根據各自的刷選條件尋找符合移除條件的對象,將符合條件的Message移除出Message鏈表,並回收該Message。