Android源码分析之Handler

时间:2023-12-14 10:28:26

  接上一篇分析,正如Android doc所说,Handler主要有2方面用处:

1. delay执行同一线程中的某个操作,也就是schedule message、runnable在未来的某一时刻执行;

2. 给另外一个线程发送message、runnable,让某个操作在另一个线程中执行。比如A线程只要能拿到B线程的

handler就能通过此handler在A线程中通过post message、runnable,让这些消息的处理发生在B线程中,从而实现

线程间的通信。AsyncTask就是通过在background线程中通过关联UI线程的handler来向UI线程发送消息的。为了看的

更清楚些,这里摘抄下Looper.java开头处给的一个典型例子:

  * This is a typical example of the implementation of a Looper thread,
* using the separation of {@link #prepare} and {@link #loop} to create an
* initial Handler to communicate with the Looper.
*
* <pre>
* 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();
* }
* }</pre>

在这里,别的线程可以通过LooperThread.mHandler来实现和它的通信。

  接下来一点点分析源码,先看几个相关的:

/**
* Callback interface you can use when instantiating a Handler to avoid
* having to implement your own subclass of Handler.
*
* @param msg A {@link android.os.Message Message} object
* @return True if no further handling is desired
*/
public interface Callback {
public boolean handleMessage(Message msg);
} /**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
} /**
* 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);
}
}

这个Callback接口里只有一个handleMessage方法返回boolean值,在后面Handler的ctor会用到,一般情况下都是null。这个接口的存在

没什么特殊的含义,只是为了让你不extends Handler就能处理消息而已(正如此方法的doc所说),类似Thread和Runnable接口的关系。

接下来是dispatchMessage方法,我们已经在上一篇分析Message的时候大概提到了。它的处理是如果message自身设置了callback,则

直接调用callback.run()方法,否则Callback接口的作用就显现了;如果我们传递了Callback接口的实现,即mCallback非空,则调用它处理

message,如果处理了(consumed)则直接返回,否则接着调用Handler自己的handleMessage方法,其默认实现是do nothing,如果你

是extends Handler,那么你应该在你的子类中为handleMessage提供自己的实现。

  接下来我们首先看看Handler都有哪些关键的字段,源码如下:

final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;
final boolean mAsynchronous;

mQueue来自mLooper,mLooper要么是在ctor中显式指定的要么是默认当前线程的,Handler关于Message、Runnable的所有处理都delegate给了mQueue;mCallback是用户提供的Callback实现,默认是null;mAsynchronous表示Handler是否是异步的,默认是同步的。

  接下来我们来看各种各样的Handler的ctor(构造器):

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

我们来看3个参数的版本,即Looper,Callback,boolean,默认looper是关联的当前线程的,callback是null,async是false。当然你愿意也可以分别指定这3个值。关于ctor不需要赘述,看doc、comment就可以很容易理解。

  接下来是一堆Handler的obtainMessage函数,其实现都是直接调用Message的静态函数obtain,但相应的message的target字段都自动被设置成了当前的Handler对象。由于Message的源码已在上一篇中分析过了,这里一带而过。

  getPostMessage(Runnable r)之类的也很简单,就是将runnable包装成一个Message,其callback字段被设置成了runnable。

  接下来的一堆postxxx、sendxxx,最终会调用下面这个方法:

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

在这里,message的target被设置成当前的Handler,如果是异步的Handler,则设置message也为异步的,然后入队,uptimeMillis表示绝对时间戳。这里需要提一下的是xxxAtFrontOfQueue方法,这个方法因为每次是将后来的message插在队列的前头,所以可能导致队列中的其他消息没机会得到处理(即饥饿),或得不到及时处理,所以说插队是不好的,慎用。正如其方法doc中所说,其实在我们的工作学习中,我也强烈推荐大家仔细看看相关类、方法的doc。我知道我们这类人都不喜欢写doc,所以既然能有doc那说明真的是必不可少的,挺重要的。

  接下来是removeCallbacks相关的,源码:

/**
* Remove any pending posts of Runnable r that are in the message queue.
*/
public final void removeCallbacks(Runnable r)
{
mQueue.removeMessages(this, r, null);
} /**
* Remove any pending posts of Runnable <var>r</var> with Object
* <var>token</var> that are in the message queue. If <var>token</var> is null,
* all callbacks will be removed.
*/
public final void removeCallbacks(Runnable r, Object token)
{
mQueue.removeMessages(this, r, token);
}

其实现也都是delegate给了mQueue,有一点需要注意下就是这些方法会remove掉所有的Runnable r,而不是第一个匹配的

(注意方法名中的s,是复数而不是单数),也就是说一次remove调用可以remove掉之前好多次post的同一个runnable,

如果之前post的runnable还在队列中的话。

  removeMessages、hasMessages之类的方法挺简单不过多解释。

  Handler类的分析就到这了。。。(由于本人水平有限,欢迎批评指正)