Android 訊息處理源碼分析(1)
Android 訊息處理源碼分析(1)
在Android中,通常被使用的訊息佇列的代碼在目錄sourcesandroid-22androidos下,涉及到以下幾個類檔案
Handler.java
Looper.java
Message.java
MessageQueue.java
Message.javapublic final class Message implements Parcelable { public int what; //訊息種類 public int arg1; //低開銷的整型參數 public int arg2; public Object obj; //Object型資料 public Messenger replyTo; //訊息處理完後通知給寄件者 /*package*/ int flags; //訊息標記:正在使用和非同步等 /*package*/ long when; //訊息建立時的時間 /*package*/ Bundle data; //訊息附帶的額外資料 /*package*/ Handler target; //訊息接受者,處理者 /*package*/ Runnable callback; //優先使用回調處理來處理訊息 /*package*/ Message next; //下一個訊息,形成鏈表 private static Message sPool; //訊息池中的頭訊息 上面中的target,通常由重新實現的Handler子類的handleMessage函數來處理訊息 public static Message obtain() { //擷取訊息的函數,如果有訊息的話則擷取出來m,鏈表指標移動一位,否則則返回一條空訊息 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(); } public void sendToTarget() { //發送訊息給處理者 target.sendMessage(this); //調用Handler.java中的函數 }}
MessageQueue.javapublic final class MessageQueue {Message mMessages; //當前要處理的訊息//當需要從鏈表中擷取一個訊息時,就會調用next函數,若訊息佇列中沒有訊息,則會阻塞等待,通過調用nativePollOnce函數來完成Message next() {...}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(MessageQueue, 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; }