Android 源码分析之Looper 、Handler、 MessageQueue 关系源码分析
2014-03-12 17:22
507 查看
引言:
Looper为一个Thread提供一个消息的循环。线程在默认的情况下是没有message loop,如果想要创建这个message loop ,需要调用 Looper.prepare(); Looper.loop(); 为了相互作用这个message loop常常使用Handler。官方提供的使用的例子:class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }在UI的主线程中不用调用 Looper.prepare(); Looper.loop(); 因为,在UI线程中系统已经调用这些方法的。(Activity是一个UI线程,运行于主线程中,Android系统在启动的时候会为Activity创建一个消息队列和消息循环(Looper)。详细实现请参考ActivityThread.java文件。)Demo:
public class MainActivity extends Activity { Handler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread() { public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(android.os.Message msg) { System.out.println(">>>" + msg.what); }; }; Looper.loop(); }; }.start(); new Thread() { public void run() { for (int i = 0; i < 100; i++) { Message msg = new Message(); msg.what = i; mHandler.sendMessage(msg); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }; }.start(); } }
1、Looper.prepare()分析
/** Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call * {@link #loop()} after calling this method, and end it by calling * {@link #quit()}. */ public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }在使用Looper.prepare()的时候,初始化了一个消息的队列。
2、Looper.loop() 分析
/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } msg.target.dispatchMessage(msg); if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycle(); } }* 通过myLooper() 返回当前线程所存在的消息的队列。 * Message msg = queue.next(); // might block 从消息队列中获取消息,这个应该是一个阻塞的消息的队列,当无消息的时候阻塞在这里,当消息到达的时候,才进行下一步的消息的传递的工作。 * msg.target.dispatchMessage(msg); 开始分发handler 消息
3 、msg.target.dispatchMessage(msg) 分析
*在Message类中 target是指一个Handler 对象在查看Handler中的 dispatchMessage,在此处分发,通过handler如何处理消息/** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }现在存在一个问题?在3处的target是怎么来的呢?
4、mHandler.sendMessage(msg) 分析
下面是消息的转发的过程/** * Pushes a message onto the end of the message queue after all pending messages * before the current time. It will be received in {@link #handleMessage}, * in the thread attached to this handler. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }
/** * Enqueue a message into the message queue after all pending messages * before (current time + delayMillis). You will receive it in * {@link #handleMessage}, in the thread attached to this handler. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. Note that a * result of true does not mean the message will be processed -- if * the looper is quit before the delivery time of the message * occurs then the message will be dropped. */ public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }
/** * Enqueue a message into the message queue after all pending messages * before the absolute time (in milliseconds) <var>uptimeMillis</var>. * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> * You will receive it in {@link #handleMessage}, in the thread attached * to this handler. * * @param uptimeMillis The absolute time at which the message should be * delivered, using the * {@link android.os.SystemClock#uptimeMillis} time-base. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. Note that a * result of true does not mean the message will be processed -- if * the looper is quit before the delivery time of the message * occurs then the message will be dropped. */ public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis); }Handler的构造函数,我们可以看到 在 public Handler(Callback callback, boolean async) 消息队列MessageQueue 是如何得到的
/** * Default constructor associates this handler with the {@link Looper} for the * current thread. * * If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown. */ public Handler() { this(null, false); } /** * Constructor associates this handler with the {@link Looper} for the * current thread and takes a callback interface in which you can handle * messages. * * If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown. * * @param callback The callback interface in which to handle messages, or null. */ public Handler(Callback callback) { this(callback, false); } /** * Use the provided {@link Looper} instead of the default one. * * @param looper The looper, must not be null. */ public Handler(Looper looper) { this(looper, null, false); } /** * Use the provided {@link Looper} instead of the default one and take a callback * interface in which to handle messages. * * @param looper The looper, must not be null. * @param callback The callback interface in which to handle messages, or null. */ public Handler(Looper looper, Callback callback) { this(looper, callback, false); } /** * Use the {@link Looper} for the current thread * and set whether the handler should be asynchronous. * * Handlers are synchronous by default unless this constructor is used to make * one that is strictly asynchronous. * * Asynchronous messages represent interrupts or events that do not require global ordering * with represent to synchronous messages. Asynchronous messages are not subject to * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. * * @hide */ public Handler(boolean async) { this(null, async); } /** * Use the {@link Looper} for the current thread with the specified callback interface * and set whether the handler should be asynchronous. * * Handlers are synchronous by default unless this constructor is used to make * one that is strictly asynchronous. * * Asynchronous messages represent interrupts or events that do not require global ordering * with represent to synchronous messages. Asynchronous messages are not subject to * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param callback The callback interface in which to handle messages, or null. * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. * * @hide */ public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; } /** * Use the provided {@link Looper} instead of the default one and take a callback * interface in which to handle messages. Also set whether the handler * should be asynchronous. * * Handlers are synchronous by default unless this constructor is used to make * one that is strictly asynchronous. * * Asynchronous messages represent interrupts or events that do not require global ordering * with represent to synchronous messages. Asynchronous messages are not subject to * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param looper The looper, must not be null. * @param callback The callback interface in which to handle messages, or null. * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. * * @hide */ public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; }
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }在MessageQueue 插入消息
boolean enqueueMessage(Message msg, long when) {if (msg.isInUse()) {throw new AndroidRuntimeException(msg + " This message is already in use.");}if (msg.target == null) {throw new AndroidRuntimeException("Message must have a target.");}synchronized (this) {if (mQuitting) {RuntimeException e = new RuntimeException(msg.target + " sending message to a Handler on a dead thread");Log.w("MessageQueue", e.getMessage(), e);return false;}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.nextprev.next = msg;}// We can assume mPtr != 0 because mQuitting is false.if (needWake) {nativeWake(mPtr);}}return true;}所以的消息都是通过 MessageQueue进行传递的。当别的线程中的通过Handler 将消息发送到消息队列中的时候,通过消息的Looper.loop(); 会不停的从MessageQueue获取消息,当消息到达的时候,通过 msg.target.dispatchMessage(msg); 调用到原来发送的消息的Handler对象,在其Handler对象所在的线程中间处理消息。参考:http://my.eoe.cn/798519/archive/10380.html http://developer.android.com/intl/zh-cn/reference/android/os/MessageQueue.html http://developer.android.com/reference/android/os/Looper.html http://developer.android.com/reference/android/os/Handler.html
相关文章推荐
- android的消息处理机制(图+源码分析)——Thread,Looper,MessageQueue,Message,Handler之间的关系
- android开发步步为营之79:通过源码分析Looper,Handler,MessageQueue之间的关系
- Android 消息机制 - Handler, Looper, Message, MessageQueue 的源码分析
- Android Handler、Looper、MessageQueue以及Message源码分析
- Handler,Looper,MessageQueue,android中的消息机制以及源码分析(一)
- Android Handler消息机制源码分析——第一部分:Looper与MessageQueue
- 从源码中分析Handler, Looper, Message, MessageQueue之间的关系
- Handler,Looper,MessageQueue,android中的消息机制以及源码分析(二)
- Android中的Looper , Handler , Message的关系,异步消息处理的机制,根据源码分析
- Android异步相关源码详细分析(Handler、Message、Looper、MessageQueue)
- [置顶] Android源码分析——Looper,Messagequeue,Message,handler初始化及handler机制简介
- android消息处理机制学习(三)-Handler,Message,MessageQueue,Looper源码分析
- Android中Looper、Handler、MessageQueue源码不完全分析
- Android消息机制(Handler,Looper,MessageQueue)-源码分析
- Handler、Message、MessageQueue、Looper关系及源码分析
- 从源码的角度分析Thread、Looper、MessageQueue、Handler的关系
- 深入Android的消息机制源码详解~Handler,MessageQueue与Looper关系
- android的消息处理机制(图+源码分析)——Looper,Handler,Message
- Android的消息处理机制(图+源码分析)——Looper,Handler,Message
- android的消息处理机制(图+源码分析)——Looper,Handler,Message