码迷,mamicode.com
首页 > 其他好文 > 详细

handler looper messageQueue 之间的关系笔记

时间:2015-01-05 21:45:44      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:

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 wake
27                 // up the event queue unless there is a barrier at the head of the queue
28                 // 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.next
42                 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 block
15             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 logger
21             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 the
34             // 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 libcore
12         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(new
29                     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 之间的关系笔记

标签:

原文地址:http://www.cnblogs.com/lihaolihao/p/4204511.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!