相关推荐:
- Android 源码阅读 | Handler
- Android 源码阅读 | Looper
- Android 源码阅读 | MessageQueue
- Android 源码阅读 | Message
- Android 自定义 View | 扭曲动效
类注释
* 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 the thread /
* message queue of the thread that is creating it -- from that point on,
* it will deliver messages and runnables to that message queue and execute
* them as they come out of the message queue.
- Handler允许用户发送 Message 和 Runnable,并进行处理。
- 每一个Handler对象都关联着一个线程和线程中的消息队列。当你创建一个新的Handler的时候,它会去绑定线程和消息队列。
- Handler创建后,它就开始工作,将 message 和 runnable 传递给消息队列,在适当的时机去处理他们。
* <p>There are two main uses for a Handler: (1) to schedule messages and
* runnables to be executed as some point in the future; and (2) to enqueue
* an action to be performed on a different thread than your own.
Handler有两个主要的作用:
- 安排 message 和 runnable 在未来的某些时刻去执行
- 向不同的线程中的消息队列发送 message 和 runnable
* <p>Scheduling messages is accomplished with the
* {@link #post}, {@link #postAtTime(Runnable, long)},
* {@link #postDelayed}, {@link #sendEmptyMessage},
* {@link #sendMessage}, {@link #sendMessageAtTime}, and
* {@link #sendMessageDelayed} methods. The <em>post</em> versions allow
* you to enqueue Runnable objects to be called by the message queue when
* they are received; the <em>sendMessage</em> versions allow you to enqueue
* a {@link Message} object containing a bundle of data that will be
* processed by the Handler's {@link #handleMessage} method (requiring that
* you implement a subclass of Handler).
- message 和 runnable 的发送由下面几个方法进行:post,postAtTime(Runnable, long),postDelayed,sendEmptyMessage,sendMessage,sendMessageAtTime,sendMessageDelayed,post相关的方法允许你发送 runnable 给消息队列,并由消息队列在适当的时机运行,sendMessage允许你发送 message 给消息队列,并在适当的时候回调对应的Handler的 handlerMessage 方法
* <p>When posting or sending to a Handler, you can either
* allow the item to be processed as soon as the message queue is ready
* to do so, or specify a delay before it gets processed or absolute time for
* it to be processed. The latter two allow you to implement timeouts,
* ticks, and other timing-based behavior.
- 当发送message或者runnable,你可以让它立即被处理,也可以延时一定时间后执行。
* <p>When a
* process is created for your application, its main thread is dedicated to
* running a message queue that takes care of managing the top-level
* application objects (activities, broadcast receivers, etc) and any windows
* they create. You can create your own threads, and communicate back with
* the main application thread through a Handler. This is done by calling
* the same <em>post</em> or <em>sendMessage</em> methods as before, but from
* your new thread. The given Runnable or Message will then be scheduled
* in the Handler's message queue and processed when appropriate.
- 应用程序创建进程后,它的主线程就会专门用于运行消息队列,该队列负责管理顶级应用程序(活动,广播接收者等)以及任何Windows的创建。
- 您可以创建自己的线程,并通过Handler与主线程进行通信,使用方法像以前一样调用 post , sendMessage 等方法,但是是来自您的新线程,然后,在消息队列中调度给定的 Runnable 或 Message ,并在适当的时候处理。
构造函数
public Handler(Callback callback, boolean async) {
//省略。。。
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;
}
在构造函数中,会绑定一个Looper和一个MessageQueue,Looper如果没有指定,则默认是当前线程的Looper,MessageQueue则是由Looper内部初始化好。消息队列的消息处理回调我们可以通过重写 void handleMessage(Message msg) 的方法,当然也可以传入一个 Callback:
public interface Callback {
public boolean handleMessage(Message msg);
}
当然,Looper我们也可以指定:
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
post 方法
post开头的方法都是发送一个 runnable 的,其有很多个:
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postAtTime(Runnable r, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
...
getPostMessage 方法,获取一个 message,其实发送的 runnable最终也是发送一个 message:
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
最终调用的方法:
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);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
最后还是调用了 messageQueue 的入队方法,可以看我们之前分析的 messageQueue 源码。
remove,sendMessage
同样的,sendMessage 是发送一个 message,remove移除一个消息或者runnable,其都是调用 messageQueue 的方法。
dispatchMessage
在 Looper 的源码里面,当从消息队列取出一个消息后,回调:dispatchMessage,
public static void loop() {
final Looper me = myLooper();
//省略...
for (;;) {
Message msg = queue.next(); // might block
//省略...
// 1. msg.target,其实就是 handler 对象,调用分发方法
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
//省略...
// 2. 分发完成后,直接 recycle 回收 messageBean
msg.recycleUnchecked();
}
}
dispatchMessage 对消息进行分发:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
在这里,如果我们实现了接口Callback,那么就不会调用handleMessage方法了。如果没有设置Callback,就会调用handleMessage。
总结
通过Handler我们可以向消息队列发送消息,和在适当的时候去处理消息。
-
所有的发送都是封装成message对象发送
-
如果我们实现了接口Callback,那么就不会调用handleMessage方法了
-
Handler默认构造函数中去绑定当前线程的Looper和MessageQueue
-
结合Android消息机制的源码,我们整体有一个流程图:
Android的消息机制不仅仅可以用在UI线程上,也可以用于你自己的子线程。以UI线程为例子,在创建UI线程的时候,会初始化一个Looper,然后Looper里面初始化好对应的消息队列MessageQueue。Looper和MessageQueue绑定,Looper遍历MessageQueue中的消息,当队列为空的时候,就阻塞当前的线程,一直无限循环,当一有消息,并且其消息的触发时机符合(msg.when<=now)则取出Message,调用Message.target.dispatchMessage方法,把消息分发到对应的Handler作处理。
- 既然Looper会阻塞UI线程,那怎么程序不会卡死掉呢?其实,正因为是阻塞线程,所以程序才不会退出。我们跑一个程序,像Java,都有一个Main函数,从Main函数入口,跑完后程序就结束了,但要想我们的程序不退出,就需要构造一个死循环,在死循环内,进行消息的处理。这里的Handler消息机制正式这样,制造一个消息队列,循环读取消息并处理。在上面的注释中知道,主线程负责管理顶级应用程序(活动,广播接收者等)以及任何Windows的创建。总结来说:
- (1)主线程由于死循环会一直不退出
- (2)发起事务处理不在循环内,而是由其他的线程发送的
- (3)它处理事务是在循环内完成的,如四大组件的相关调用
码字不易,方便的话素质三连,或者关注我的公众号 技术酱,专注 Android 技术,不定时推送新鲜文章,如果你有好的文章想和大家分享,欢迎关注投稿!