首页 > 代码库 > handler looper messageQueue 之间的关系笔记

handler looper messageQueue 之间的关系笔记

handler 主要用于发送消息和接收消息,handler可以更新ui延时更新ui
looper 主要用于从消息队列中循环读取消息并把消息发送给handler
messageQueue 是一个消息队列,用来存储消息。

 

下面从源码的角度分析三者的关系:

Handler handler = new Handler(){            @Override            public void handleMessage(Message msg) {                super.handleMessage(msg);            }                    };handler.sendEmptyMessage(1);
public Handler() {        this(null, false);}
 1  public Handler(Callback callback, boolean async) { 2         if (FIND_POTENTIAL_LEAKS) { 3             final Class<? extends Handler> klass = getClass(); 4             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && 5                     (klass.getModifiers() & Modifier.STATIC) == 0) { 6                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " + 7                     klass.getCanonicalName()); 8             } 9         }10 11         mLooper = Looper.myLooper();12         if (mLooper == null) {13             throw new RuntimeException(14                 "Can‘t create handler inside thread that has not called Looper.prepare()");15         }16         mQueue = mLooper.mQueue;17         mCallback = callback;18         mAsynchronous = async;19     }

看到11行 就可以看到handler联系在一块了获取一个looper对象

1     public static Looper myLooper() {2         return sThreadLocal.get();3     }

下面看一下

handler.sendEmptyMessage(1);
里面做了什么东东!
经过一路跟踪来到了
 1  public boolean sendMessageAtTime(Message msg, long uptimeMillis) { 2         MessageQueue queue = mQueue; 3         if (queue == null) { 4             RuntimeException e = new RuntimeException( 5                     this + " sendMessageAtTime() called with no mQueue"); 6             Log.w("Looper", e.getMessage(), e); 7             return false; 8         } 9         return enqueueMessage(queue, msg, uptimeMillis);10     }

下面看看

enqueueMessage(queue, msg, uptimeMillis) 做了什么

1     private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {2         msg.target = this;3         if (mAsynchronous) {4             msg.setAsynchronous(true);5         }6         return queue.enqueueMessage(msg, uptimeMillis);7     }

看到第2行 其实就知道了 message跟handler关联起来了 msg.target 就是当前的handler实例。

现在我们来看一下MessageQueue类中enqueueMessage()这个方法做了什么!其实想一下也知道肯定是往消息队列尾部添加一个消息

下面我们看看该方法

 1  final boolean enqueueMessage(Message msg, long when) { 2         if (msg.isInUse()) { 3             throw new AndroidRuntimeException(msg + " This message is already in use."); 4         } 5         if (msg.target == null) { 6             throw new AndroidRuntimeException("Message must have a target."); 7         } 8  9         boolean needWake;10         synchronized (this) {11             if (mQuiting) {12                 RuntimeException e = new RuntimeException(13                         msg.target + " sending message to a Handler on a dead thread");14                 Log.w("MessageQueue", e.getMessage(), e);15                 return false;16             }17 18             msg.when = when;19             Message p = mMessages;20             if (p == null || when == 0 || when < p.when) {21                 // New head, wake up the event queue if blocked.22                 msg.next = p;23                 mMessages = msg;24                 needWake = mBlocked;25             } else {26                 // Inserted within the middle of the queue.  Usually we don‘t have to wake27                 // up the event queue unless there is a barrier at the head of the queue28                 // and the message is the earliest asynchronous message in the queue.29                 needWake = mBlocked && p.target == null && msg.isAsynchronous();30                 Message prev;31                 for (;;) {32                     prev = p;33                     p = p.next;34                     if (p == null || when < p.when) {35                         break;36                     }37                     if (needWake && p.isAsynchronous()) {38                         needWake = false;39                     }40                 }41                 msg.next = p; // invariant: p == prev.next42                 prev.next = msg;43             }44         }45         if (needWake) {46             nativeWake(mPtr);47         }48         return true;49     }

我们很清楚的看到了 22和41行把这个消息next  就把这个消息添加到了消息队列中,我们把

handler.sendEmptyMessage(1);分析完了 
那么发送过消息后怎么又回调到 Handler的handleMessage方法中呢!
 public void handleMessage(Message msg) {                super.handleMessage(msg); }
下面不得不说说looper了 
看一下looper两个重要的方法
 1     public static void prepare() { 2         prepare(true); 3     } 4  5     private static void prepare(boolean quitAllowed) { 6         if (sThreadLocal.get() != null) { 7             throw new RuntimeException("Only one Looper may be created per thread"); 8         } 9         sThreadLocal.set(new Looper(quitAllowed));10     }11 12     private Looper(boolean quitAllowed) {13         mQueue = new MessageQueue(quitAllowed);14         mRun = true;15         mThread = Thread.currentThread();16     }

执行prepare 方法就是新建一个looper对象和MessageQueue对象

再看一下looper 的另外一个重要的方法

 1   public static void loop() { 2         final Looper me = myLooper(); 3         if (me == null) { 4             throw new RuntimeException("No Looper; Looper.prepare() wasn‘t called on this thread."); 5         } 6         final MessageQueue queue = me.mQueue; 7  8         // Make sure the identity of this thread is that of the local process, 9         // and keep track of what that identity token actually is.10         Binder.clearCallingIdentity();11         final long ident = Binder.clearCallingIdentity();12 13         for (;;) {14             Message msg = queue.next(); // might block15             if (msg == null) {16                 // No message indicates that the message queue is quitting.17                 return;18             }19 20             // This must be in a local variable, in case a UI event sets the logger21             Printer logging = me.mLogging;22             if (logging != null) {23                 logging.println(">>>>> Dispatching to " + msg.target + " " +24                         msg.callback + ": " + msg.what);25             }26 27             msg.target.dispatchMessage(msg);28 29             if (logging != null) {30                 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);31             }32 33             // Make sure that during the course of dispatching the34             // identity of the thread wasn‘t corrupted.35             final long newIdent = Binder.clearCallingIdentity();36             if (ident != newIdent) {37                 Log.wtf(TAG, "Thread identity changed from 0x"38                         + Long.toHexString(ident) + " to 0x"39                         + Long.toHexString(newIdent) + " while dispatching to "40                         + msg.target.getClass().getName() + " "41                         + msg.callback + " what=" + msg.what);42             }43 44             msg.recycle();45         }46     }

我们看到这个是“死循环”,看27行

 msg.target.dispatchMessage(msg);
其实就是调用的handler 的
dispatchMessage()方法,看一下这个方法
 1     /** 2      * Handle system messages here. 3      */ 4     public void dispatchMessage(Message msg) { 5         if (msg.callback != null) { 6             handleCallback(msg); 7         } else { 8             if (mCallback != null) { 9                 if (mCallback.handleMessage(msg)) {10                     return;11                 }12             }13             handleMessage(msg);14         }15     }

呵呵终于看到 handleMessage方法回调了。大功告成。

看到别人的博看上面讲 looper的prepare和loop()方法在activity初始化时就执行了,以前死活找不到在哪执行了

今天终于找到了

 1  public static void main(String[] args) { 2         SamplingProfilerIntegration.start(); 3  4         // CloseGuard defaults to true and can be quite spammy.  We 5         // disable it here, but selectively enable it later (via 6         // StrictMode) on debug builds, but using DropBox, not logs. 7         CloseGuard.setEnabled(false); 8  9         Environment.initForCurrentUser();10 11         // Set the reporter for event logging in libcore12         EventLogger.setReporter(new EventLoggingReporter());13 14         Process.setArgV0("<pre-initialized>");15 16         Looper.prepareMainLooper();17 18         ActivityThread thread = new ActivityThread();19         thread.attach(false);20 21         if (sMainThreadHandler == null) {22             sMainThreadHandler = thread.getHandler();23         }24 25         AsyncTask.init();26 27         if (false) {28             Looper.myLooper().setMessageLogging(new29                     LogPrinter(Log.DEBUG, "ActivityThread"));30         }31 32         Looper.loop();33 34         throw new RuntimeException("Main thread loop unexpectedly exited");35     

尼玛原来就在16和32行 哎呦好像看到main方法了  这个代码在ActivityThread类中



 

handler looper messageQueue 之间的关系笔记