版本基于:Android R
之前
Android 基于Handler 剖析消息机制 一文中完成地剖析了Android 中异步消息处理的流程。
0. 前言
Handler 的描述很详细:
/**
* A Handler allows you to send and process {@link Message} and Runnable
* objects associated with a thread's {@link MessageQueue}. Each Handler
* instance is associated with a single thread and that thread's message
* queue. When you create a new Handler it is bound to a {@link Looper}.
* It will deliver messages and runnables to that Looper's message
* queue and execute them on that Looper's thread.
Handler 是用来发送和处理与一个线程的 MessageQueue 有关联的 Message 和 Runnable。
一个 Handler 与一个线程以及此线程的MessageQueue有关联。
新建一个Handler 的时候,要与一个 已经创建好的线程 的 MessageQueue 绑定。这样Handler 就可以发送message 和runnable 到消息队列,并且处理从消息队列发出来的回调。
1. 构造函数
Handler 类的构造函数有7 个,但是最终可以提炼出两个,以参数有无looper 区分。
主要来看一下:
frameworks/base/core/java/android/os/Handler.java
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) {
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 " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
通过构造函数可以看到,handler 是创建的时候可以不传Looper,那也就是说这个时候的handler 是在实例它的线程 Looper.myLooper() 中。
在应用中可能一些费时、阻塞的东西可以通过消息队列来处理,这个时候可以新建一个Thread,将Thread 中处理消息队列,最后通过 handleMessage() 在主线程中处理UI 的操作。
2. 搭建消息队列
通过 Handler sendMessage 与 obtainMessage (sendToTarget)比较 看到,我们还是尽量用obtainMessage() 来获取msg obj:
frameworks/base/core/java/android/os/Message.java
public final Message obtainMessage(int what)
{
return Message.obtain(this, what);
}
至于new Message() 与obtainMessage() 有什么区别,可以看一下Handler sendMessage 与 obtainMessage (sendToTarget)比较
sendMessage() 有两个选择:
- 通过自身线程的Handler发送消息,消息会存放在本线程的MessageQueue中
- 通过另外线程的Handler发送消息,消息会存放在另外线程的MessageQueue中
frameworks/base/core/java/android/os/Message.java
public void sendToTarget() {
target.sendMessage(this);
}
最终会调用到:
frameworks/base/core/java/android/os/Handler.java
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);
}
最终会往handler 所在的Lopper 里面的MessageQueue 存msg。
通过 Android 基于Handler 剖析消息机制 知道 Looper.loop() 就是一直处理消息队列,没有就挂靠起来。loop 会去处理每一个msg:
msg.target.dispatchMessage(msg);
frameworks/base/core/java/android/os/Handler.java
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
这个逻辑也是需要注意的:
- 当Message 中有Runnable 处理的时候,会去处理Runnable
该 Runnable 可以通过Handler 中的接口设置,最终都是通过 Message.obtain() 存入到 message 中,如下:
frameworks/base/core/java/android/os/Handler.java
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postAtTime(Runnable r, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
public final boolean postDelayed(Runnable r, long delayMillis)
{
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
public final boolean postAtFrontOfQueue(Runnable r)
{
return sendMessageAtFrontOfQueue(getPostMessage(r));
}
private static Message getPostMessage(Runnable r, Object token) {
Message m = Message.obtain();
m.obj = token;
m.callback = r;
return m;
}
- 如果没有Runnable 有Callback 的时候,处理Callback
public interface Callback {
public boolean handleMessage(Message msg);
}
- 如果上面都没有,如果需要处理msg,就需要override handler 中的成员函数
public void handleMessage(Message msg) {
}
删除Runnable 和 msg 可以通过:
public final void removeCallbacks(Runnable r)
{
mQueue.removeMessages(this, r, null);
}
public final void removeCallbacks(Runnable r, Object token)
{
mQueue.removeMessages(this, r, token);
}
public final void removeMessages(int what) {
mQueue.removeMessages(this, what, null);
}
public final void removeMessages(int what, Object object) {
mQueue.removeMessages(this, what, object);
}
还有一个Android 类可以直接用,可以看一下 Android HandlerThread