首页 > 代码库 > 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 之间的关系笔记
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。