Android-Handler源码解析-Handler
源码版本:
- Handler:SDK-31
导航:
成员变量
// 是否发现(检查)潜在的泄漏
private static final boolean FIND_POTENTIAL_LEAKS = false;
// Log的Tag
private static final String TAG = "Handler";
// 主线程Handler
private static Handler MAIN_THREAD_HANDLER = null;
// 此Handler的Looper
@UnsupportedAppUsage
final Looper mLooper;
// 此Handler的消息队列,来自Looper对象。
final MessageQueue mQueue;
// 此Handler分发消息时,优先处理消息的Callback。
@UnsupportedAppUsage
final Callback mCallback;
// 是否是异步Handler,即是否send或post的消息全部都是异步消息,默认为false。
final boolean mAsynchronous;
// 跨进程通信,消息发送者。
@UnsupportedAppUsage
IMessenger mMessenger;
说明:
Handler
为什么需要持有Looper
、MessageQueue
,因为Handler
发送消息等操作需要知道发送到哪个MessageQueue
,而MessageQueue
需要从Looper
中获取,以便发出的消息能进行轮询分发 。Looper
相关介绍,请看Android-Handler源码解析-Looper。MessageQueue
相关介绍,请看Android-Handler源码解析-MessageQueue。
创建Handler
想要使用Handler
,首先要创建Handler
,所以我们接下来看下它是如何被创建的。
new Handler()
默认Looper
Handler()
@Deprecated
public Handler() {
this(null, false);
}
Handler(Callback)
@Deprecated
public Handler(@Nullable Callback callback) {
this(callback, false);
}
Handler(Callback, boolean)
/** @hide */
public Handler(@Nullable 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) {
// 匿名类、成员类、局部类,并且不是静态的,警告提示(以下Handler类应该是静态的,否则可能会发生泄漏)。
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
// 获取当前线程的Looper
mLooper = Looper.myLooper();
if (mLooper == null) {
// 当前线程没有Looper,则抛出异常提示(不能在没有调用Looper.prepare()的线程中创建handler)。
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
// 获取Looper的消息队列
mQueue = mLooper.mQueue;
// 记录CallBack
mCallback = callback;
// 记录是否是异步的
mAsynchronous = async;
}
以上构造方法,使用默认的Looper
(当前线程的Looper
)。如果这个线程没有looper
,则抛出异常。
说明:
Handler()
、Handler(Callback)
两个构造方法已经被标记为@Deprecated
(过时),因为在Handler
构造过程中隐式选择一个Looper
可能会导致错误,其中操作会自动丢失(如果Handler
不需要新任务并退出)、崩溃(如果handler
有时是在一个没有激活Looper
线程上创建的),或者竞态条件,其中handler
关联的线程与作者预期的不符。相反,可以使用java.util.concurrent.Executor
,或者使用Looper.getMainLooper
,{link
android.view.View#getHandler
}或类似工具显式指定Looper
。如果为了兼容性需要隐藏thread local
行为,则使用new Handler(Looper.myLooper())
让读者更清楚。Handler(Callback, boolean)
两个构造方法已经被标记为@hide
(隐藏),只能系统内部使用。- 使用默认的
Looper
(当前线程的Looper
),如果这个线程没有looper
,则抛出异常。- 参数
Callback
,为此Handler
分发消息时,优先处理消息的Callback
,详细见后面-分发Message。- 参数
async
,为此Handler
发送消息时,是否全部发送异步/同步(默认同步)消息,详细见后面-发送Message。- 异步消息表示不需要对同步消息进行全局排序的中断或事件。 异步消息不受
MessageQueue.postSyncBarrier(long)
引入的同步屏障的影响。MessageQueue
同步屏障相关介绍,请看Android-Handler源码解析-MessageQueue-同步屏障。
指定Looper
Handler(Looper)
public Handler(@NonNull Looper looper) {
this(looper, null, false);
}
Handler(Looper, Callback)
public Handler(@NonNull Looper looper, @Nullable Callback callback) {
this(looper, callback, false);
}
Handler(Looper, Callback, boolean)
/** @hide */
@UnsupportedAppUsage
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
以上构造方法,使用指定的Looper
而不是默认的Looper
。
说明:
Handler(Looper)
、Handler(Looper, Callback)
两个构造方法未被标记为@Deprecated
(过时),并使用指定的Looper
,推荐使用。Handler(Looper, Callback, boolean)
构造方法已经被标记为@hide
(隐藏),只能系统内部使用。
Handler.createAsync()
Handler.createAsync(Looper)
@NonNull
public static Handler createAsync(@NonNull Looper looper) {
if (looper == null) throw new NullPointerException("looper must not be null");
return new Handler(looper, null, true);
}
Handler.createAsync(Looper, Callback)
@NonNull
public static Handler createAsync(@NonNull Looper looper, @NonNull Callback callback) {
if (looper == null) throw new NullPointerException("looper must not be null");
if (callback == null) throw new NullPointerException("callback must not be null");
return new Handler(looper, callback, true);
}
Handler.createAsync()
方法,为静态方法,创建一个异步Handler
,其发布的Message
不受同步障碍(如显示vsync
)的影响。
说明:
- 发送到异步
handler
的消息可以保证彼此之间的顺序,但不一定要按照来自其他Handlers
的消息进行排序。
小结
- 创建-同步
Handler
,分为未指定Looper
、指定Looper
两种方式创建。
- 未指定
Looper
,则使用当前线程的Looper
,不推荐使用。- 指定
Looper
,推荐使用,构造方法为Handler(Looper)
、Handler(Looper, Callback)
。
- 创建-异步
Handler
,使用Handler.createAsync(Looper)
、Handler.createAsync(Looper, Callback)
方法创建。
创建Message
想要使用Message
,可以通过Handler
创建Message
,所以我们接下来看下它是如何被创建的。
obtainMessage()
@NonNull
public final Message obtainMessage() {
return Message.obtain(this);
}
@NonNull
public final Message obtainMessage(int what) {
return Message.obtain(this, what);
}
@NonNull
public final Message obtainMessage(int what, @Nullable Object obj) {
return Message.obtain(this, what, obj);
}
@NonNull
public final Message obtainMessage(int what, int arg1, int arg2) {
return Message.obtain(this, what, arg1, arg2);
}
@NonNull
public final Message obtainMessage(int what, int arg1, int arg2, @Nullable Object obj) {
return Message.obtain(this, what, arg1, arg2, obj);
}
以上obtainMessage()
方法 ,从全局消息池返回一个新的消息。内部使用Message.obtain()
方法创建消息,并将其Message
的target
为当前Handler
。
说明:
Message.obtain()
相关介绍,请看Android-Handler源码解析-Message-创建Message。
小结
handler.obtainMessage()
方法,使用Message.obtain()
方法创建消息,并将其Message
的target
为当前Handler
。
发送Message
Message
创建好后,便可以发送消息了,Handler
除了可以通过sendMessage()
方法发送消息,还可以通过post()
方法执行指定的Callback
任务,所以我们接下来看下它们是如何被发送的。
send-Message
sendMessage()
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
sendEmptyMessage()
public final boolean sendEmptyMessage(int what) {
return sendEmptyMessageDelayed(what, 0);
}
sendEmptyMessageDelayed()
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
sendEmptyMessageAtTime()
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
sendMessageDelayed()
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
sendMessageAtTime()
public boolean sendMessageAtTime(@NonNull 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);
}
sendMessageAtFrontOfQueue()
public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg) {
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, 0);
}
以上方法,为发送立即消息、发送延迟消息、发送指定时刻消息、将消息排在消息队列的前面。
说明:
sendMessage()
、sendEmptyMessage()
为发送立即消息消息,sendMessageDelayed()
、sendEmptyMessageDelayed()
为发送延迟消息消息,sendMessageAtTime()
为发送指定时刻消息,sendMessageAtFrontOfQueue()
为将消息排在消息队列的前面。sendMessageAtFrontOfQueue()
,为将消息排在消息队列的前面,以便在消息loop
的下一次迭代中处理。此方法仅用于非常特殊的情况——它很容易使消息队列挨饿、导致排序问题或产生其它意想不到的副作用。- 发送立即消息、发送延迟消息、指定时刻发送、将消息排在消息队列的前面,他们最终调用的都是
enqueueMessage()
方法。
我们接下来看下enqueueMessage()
方法。
enqueueMessage()
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
// 指定Message的Handler为此Handler
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
// 如果此Handler是异步的,则发送的所有消息都是异步的。
if (mAsynchronous) {
msg.setAsynchronous(true);
}
// 使用MessageQueue将消息加入到消息队列中
return queue.enqueueMessage(msg, uptimeMillis);
}
enqueueMessage()
方法,为将Message
加入到MessageQueue
中。
说明:
- 指定此
Message
的target
为此Handler
,使此Message
和此Handler
关联,以便使用此Handler
处理此Message
。- 如果此
Handler
是异步的,则发送的所有消息都是异步的。uptimeMillis
参数为消息执行时刻,立即执行的为SystemClock.uptimeMillis()
,延时执行的为SystemClock.uptimeMillis() + delayMillis
,指定时刻发送的为指定的
,将消息排在消息队列的前面的为0
。MessageQueue
入队消息相关介绍,请看Android-Handler源码解析-MessageQueue-入队Message。
post-Callback
post()
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
postAtTime()
public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
public final boolean postAtTime(@NonNull Runnable r, @Nullable Object token, long uptimeMillis) {
return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
postDelayed()
public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
public final boolean postDelayed(@NonNull Runnable r, @Nullable Object token, long delayMillis) {
return sendMessageDelayed(getPostMessage(r, token), delayMillis);
}
postAtFrontOfQueue()
public final boolean postAtFrontOfQueue(@NonNull Runnable r) {
return sendMessageAtFrontOfQueue(getPostMessage(r));
}
以上方法,为执行指定的Callback
任务,由Runnable
实现。底层也是通过getPostMessage()
方法将Runnable
包装为Message
然后调用对应的发送消息的方法进行发送,发送消息详细看上面的-send-Message。
接下来我们来看一下getPostMessage()
方法的实现。
getPostMessage()
private static Message getPostMessage(Runnable r) {
// 使用复用获取新的Message
Message m = Message.obtain();
// 将Runnable保存到Message的callback中
m.callback = r;
return m;
}
@UnsupportedAppUsage
private static Message getPostMessage(Runnable r, Object token) {
Message m = Message.obtain();
m.obj = token;
m.callback = r;
return m;
}
getPostMessage()
方法,使用复用机制获取新的Message
,并将Runnable
保存到Message
的callback
中。
小结
- 发送消息分为
send-Message
、post-Callback
,post-Callback
底层也是通过send-Message
进行发送(将Runnable
保存到Message
的callback
中)。sendMessageAtFrontOfQueue()
、postAtFrontOfQueue()
,方法为将消息排在消息队列的前面,会使原来有序的队列变为无序的,谨慎使用。- 通过
handler
发送的消息,最终都会将此Message
和此Handler
关联,以便使用此Handler
处理此Message
。- 如果此
Handler
是异步的,则发送的所有消息都是异步的。
分发Message
当Looper.loop()
方法开启后,并且此Looper
的MessageQueue
的next()
方法返回一个Message
后,会调用Handler
的dispatchMessage()
方法,代码如下。
Loop->loopOnce()
private static boolean loopOnce(final Looper me,
final long ident, final int thresholdOverride) {
Message msg = me.mQueue.next(); // might block
...
// 调用Handler分发消息
msg.target.dispatchMessage(msg);
...
}
接下来我们来看一下Handler
的dispatchMessage()
方法。
dispatchMessage()
Handler->dispatchMessage()
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
// 处理Callback
handleCallback(msg);
} else {
// 处理Message
if (mCallback != null) {
// handler的Callback不为空,优先它处理。
if (mCallback.handleMessage(msg)) {
// 返回true,表示handler的Callback已经处理,不再需要handleMessage()方法处理。
return;
}
}
// 使用handleMessage方法处理
handleMessage(msg);
}
}
dispatchMessage()
方法,为分发消息,分为处理Callback
、处理Message
,而的处理Message
优先handler
的Callback
处理,其次再handleMessage()
方法处理。
说明:
dispatchMessage()
方法为public
并且不是final
,所以可以被覆写,一般不覆写此方法。
接下来我们先来看一下处理Callback
的handleCallback()
方法。
handleCallback()
private static void handleCallback(Message message) {
// 调用callback.run()方法(即runnable.run()方法)执行
message.callback.run();
}
handleCallback()
方法,直接调用message
的callback
(即Runnable
)的run()
方法执行。
接下来我们再来看一下优先处理Message
的Handler.Callback
类,其次再来看一下其次处理的handleMessage()
方法。
Handler.Callback类
public interface Callback {
/**
* @return 如果不需要进一步处理,则为True。
*/
boolean handleMessage(@NonNull Message msg);
}
如果handler.mCallback
有设置值,则优先它来处理,并且handleMessage()
方法返回true
,则不再需要handleMessage()
方法处理。
handleMessage()
public void handleMessage(@NonNull Message msg) {
}
handleMessage()
方法,为处理消息,我们可以通过Message
的what
的值来区分,来实现自己的逻辑。
说明:
handleMessage()
方法为public
并且不是final
,所以可以被覆写,一般覆写此方法。
小结
- 分发
Message
,它是通过Handler
的dispatchMessage()
方法进行分发处理。- 分发
Message
,它分为处理Callback
、处理Message
。
2.1.处理Callback
,直接调用callback
(即Runnable
)的run()
方法执行。
2.2.处理Message
,优先handler
的Callback
处理,其次再handleMessage()
方法处理。dispatchMessage()
、handleMessage()
方法均可以被覆写,一般只覆写handleMessage()
方法即可。
移除Messages、Callbacks
removeMessages()
public final void removeMessages(int what) {
mQueue.removeMessages(this, what, null);
}
public final void removeMessages(int what, @Nullable Object object) {
mQueue.removeMessages(this, what, object);
}
removeCallbacks()
public final void removeCallbacks(@NonNull Runnable r) {
mQueue.removeMessages(this, r, null);
}
public final void removeCallbacks(@NonNull Runnable r, @Nullable Object token) {
mQueue.removeMessages(this, r, token);
}
removeCallbacksAndMessages()
public final void removeCallbacksAndMessages(@Nullable Object token) {
mQueue.removeCallbacksAndMessages(this, token);
}
以上方法,为移除指定what
的Message
或指定runnable
的Callbacks
,全部都是通过调用MessageQueue
的removeXX
方法进行移除。
说明:
MessageQueue
移除消息相关介绍,请看Android-Handler源码解析-MessageQueue-移除Message。
小结
- 移除
Messages
、Callbacks
,removeMessages()
、removeCallbacks()
、removeCallbacksAndMessages()
方法,分别为移除所有符合条件的Messages、Callbacks。
是否有Messages、Callbacks
hasMessages()
public final boolean hasMessages(int what) {
return mQueue.hasMessages(this, what, null);
}
hasCallbacks()
public final boolean hasCallbacks(@NonNull Runnable r) {
return mQueue.hasMessages(this, r, null);
}
hasMessagesOrCallbacks()
public final boolean hasMessagesOrCallbacks() {
return mQueue.hasMessages(this);
}
以上方法,为判断是否有指定what
的Message
或指定runnable
的Callbacks
,全部都是通过调用MessageQueue
的hasMessages
方法进行判断。
说明:
MessageQueue
是否有消息相关介绍,请看Android-Handler源码解析-MessageQueue-是否有Message。
小结
- 是否有
Messages
、Callbacks
,hasMessages()
、hasCallbacks()
、hasMessagesOrCallbacks()
方法,分别为判断是否有符合条件的Messages、Callbacks。
其它
getMessageName()
public String getMessageName(@NonNull Message message) {
if (message.callback != null) {
// 是Callback类型,返回此Callback(即Runnable)的类名。
return message.callback.getClass().getName();
}
// 是Message类型,返回此Message的what的十六进制。
return "0x" + Integer.toHexString(message.what);
}
获取表示指定Message
名称的字符串。默认实现,是Callback
类型返回此Callback
(即Runnable
)的类名,是Message
类型返回此Message
的what
的十六进制。
getLooper()
@NonNull
public final Looper getLooper() {
return mLooper;
}
获取此Handler
的Looper
对象
dump()
public final void dump(@NonNull Printer pw, @NonNull String prefix) {
pw.println(prefix + this + " @ " + SystemClock.uptimeMillis());
if (mLooper == null) {
pw.println(prefix + "looper uninitialized");
} else {
mLooper.dump(pw, prefix + " ");
}
}
转储looper
的状态,以进行调试。如果Looper
为空,直接打印,否则调用Looper
的dump()
方法。
说明:
Looper
转储的相关介绍,请看Android-Handler源码解析-Looper-其它。
总结
以上就是Handler
源码的Handler
源码部分,Handler
其它源码部分看下面导航。之后会出其它Android
源码系列,请及时关注。如果你有什么问题,大家评论区见!
导航:
最后推荐一下我的网站,开发者的技术博客: devbolg.cn ,目前包含android相关的技术,之后会面向全部开发者,欢迎大家来体验!