也來解釋一下android的MessageQueue源碼

    大三了,老想自己寫點市面上沒有的東西,這些天在嘗試寫一個可以用鼠標操作手機的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();
        }
    }
}

發佈了21 篇原創文章 · 獲贊 16 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章