Looper: Looper,Handler,MessageQueue三者之间的联系

mac2022-06-30  111

在Android中每个应用的UI线程是被保护的,不能在UI线程中进行耗时的操作,其他的子线程也不能直接进行UI操作。为了达到这个目的Android设计了handler Looper这个系统框架,Android 推荐把耗时的操作放到子线程中去执行,子线程执行完毕后如果想通知UI更新,可以通过给主线程的Handler发送Message的方式来予以实现,说起Handler就不得不提到它的另外两个伙伴:Looper和MessageQueue,它们三者之间的关系如下:

 

Handler: 消息处理者(发送消息和处理消息)。MessageQueue: 消息队列(承载消息的容器)。Looper: 管理者(管理消息队列,不断的从MessageQueue中读取消息交给Handler进行处理)。

 

以子线程向主线程发送一条消息为例,当在一条子线程中调用mHandler.sendMessage(msg)时,它的执行过程如下:

1. Handler会依次调用 sendMessageDelayed() 、 sendMessageAtTime() 、 enqueueMessage() 方法将消息压入MessageQueue。

1.1 sendMessage

/** * 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); }

1.2 sendMessageDelayed

/** * 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); }

1.3 sendMessageAtTime

/** * 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> * Time spent in deep sleep will add an additional delay to execution. * 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); }

这里的mQueue其实是Handler已经持有的一个成员变量,在Handler的构造方法中通过Looper对象身上获取到的,Looper对象本身就含有一个MessageQueue。

/** * 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 respect 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; }

1.4 enqueueMessage

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }

在enqueueMessage方法中通过调用MessageQueue的enqueueMessage()方法将消息压入消息队列。

2. 以上是入队的操作,接下来主线程通过Looper.loop()方法不断的从消息队列中获取消息,并交给其指定的Handler进行处理:

这里有个问题,主线程的Looper是什么时候启动的?我们知道,Google设计Looper的目的就是为了在一个线程里运行一个消息循环,但是Looper需要调用 prepare() 方法才能运行起来,调用 loop() 方法开始处理消息。那么这两个方法在哪里开始调用的?

一般说来,Android程序的入口点可以认为是android.app.ActivityThread类的main()方法(Android 2.3):

public static final void main(String[] args) { SamplingProfilerIntegration.start(); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); if (sMainThreadHandler == null) { sMainThreadHandler = new Handler(); } ActivityThread thread = new ActivityThread(); thread.attach(false); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop(); if (Process.supportsProcesses()) { throw new RuntimeException("Main thread loop unexpectedly exited"); } thread.detach(); String name = (thread.mInitialApplication != null) ? thread.mInitialApplication.getPackageName() : "<unknown>"; Slog.i(TAG, "Main thread of " + name + " is now exiting"); }

果然,在这个方法里找到了prepare()和loop()方法的调用,这说明程序在启动的时候就自动开始了Looper的运转。接下来就要看出队的操作了,Looper通过调用loop()方法开始处理消息,来到Looper.java:

2.1 loop()

public static final void loop() { Looper me = myLooper(); MessageQueue queue = me.mQueue; while (true) { Message msg = queue.next(); // might block if (msg != null) { if (msg.target == null) { return; } if (me.mLogging!= null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); msg.target.dispatchMessage(msg); if (me.mLogging!= null) me.mLogging.println( "<<<<< Finished to " + msg.target + " " + msg.callback); msg.recycle(); } } }

可以看到,它内部起了一个死循环,并不断的从队列中获取Message, 然后通过调用  msg.target.dispatchMessage(msg); 方法将消息分发出去, 这里的target就是之前指定处理该消息的Handler, 从这里也可以看出,一个界面可以有很多个Handler,因为最终消息都会被分发到它所指定的那个Handler上面去。

2.2 dispatchMessage

public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }

这里首先对Message的callback做了判断,如果它自身的callback不为空,就调用handleCallback处理该消息,那什么时候Message的callback不为空呢?其实是在调用Handler的post(Runnable r)方法发送消息的时候:

/** * Causes the Runnable r to be added to the message queue. * The runnable will be run on the thread to which this handler is * attached. * * @param r The Runnable that will be executed. * * @return Returns true if the Runnable 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 post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } Handler#post(Runnable r) private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; } getPostMessage

那这个mCallback是个什么东西呢,它其实是Handler的构造方法中传入的用于处理具体msg的一个类:

/** * 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 respect 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; }

接下来就很简单了,如果mCallback不为null,就调用了mCallback的handleMessage来处理消息,如果mCallback为null,就直接调用Handler的handleMessage来处理消息,注意到,Handle本身的handleMessage()方法其实是个空方法:

/** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { }

我们一般在使用Handler在处理Message的时候都会将其重写。

 

总结:整个执行流程就是:

1.Handler先将指定的Message压入到Looper对象的MessageQueue中;

2.Looper对象会调用loop()方法不断的从MessageQueue中获取消息;

3.当拿到一条消息后,会根据该Message的target选择合适的Handler并调用其handleMessage()方法对消息进行处理。

参考链接:

1. 郭神-Android异步消息处理机制完全解析,带你从源码的角度彻底理解

2.Android源代码在线

3.Android中为什么主线程不会因为Looper.loop()方法造成阻塞

 

转载于:https://www.cnblogs.com/yongdaimi/p/11558815.html

最新回复(0)