1 什么是Handler
以下内容摘自Android官方原文:
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.
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允许你发送和处理与线程相关的消息,runnable类型的对象。每一个Handle和一个单一的线程,线程队列对应。当你创建一个Handler,Handler是绑定到一个线程/线程队列,从那时起,它会将消息和runnable传递给该消息队列,并且执行这些消息止到他们从消息队列中走出。
Handler主要有两个用处:
1.安排消息和runnables将在未来的某个点上执行
2.在其他线程中,插入一个操作在Handler所在的线程(即用户线程间通讯)
2 Message MessageQueue Looper
谈到Handler,需要先了解下Message,MessageQueue,Looper,以及他们与Handler的关系
2.1 Message
Message,消息,用于在线程之间传递数据。Message 对象可以通过 new 关键字来获得,但为了节省资源,通常使用 Message.obtain() 方法或 Handler.obtainMessage() 方法来从消息池中获得空消息对象。下面是它的属性:
- arg1: 用来存放 int 型数据;
- arg2: 用来存放 int 型数据;
- obj: 用来存放 Object 数据(即存放对象);
- what: 用于指定用户自定义的消息代码,便于主线程接收后,根据不同的消息代码执行不同的操作;
- setData(Bundle): 传送复杂的数据。
2.2 MessageQueue
MeessageQueue,消息队列,用来存放所有通过 Handler 发送的消息,这部分消息会一直存在消息队列中,等待被处理,(按照 FIFO (先进先出) 的规则执行);一个线程中只会有一个 MessageQueue 对象。
2.3 Looper
Looper,消息泵,是每个线程中 MessageQueue 的管家,调用 Looper 的 loop() 方法后,就会进入到一个无限循环中,每当发现 MessageQueue 中存在一条消息,Looper 就会将它取出,并传递到 Handler 的 handleMessage()方法中。一个线程中只会有一个 Looper 对象。
2.4 Handler Lopper Message MessageQueue之间的关系
- 如图,Handler 是寄信人,负责把 Message 放到 MessageQueue 里面去;Message 是信件;MessageQueue 是邮筒,先进来的信件会先被取出;Looper 是邮差,负责管理 Message(信件),当 MessageQueue(邮筒) 里有 Message(信件) 时,就将其取出,然后交给 Handler(收信人) 处理;其中,Handler 既是寄信人,又是收信人。
- 一个线程中只能有一个 Looper 对象和 MessageQueue 对象,但是可以有多个 Handler 和 Message;多个 Handler 可以共享一个 Looper 和 MessageQueue,但一个 Handler 只能有一个 MessageQueue;Message 被存放在 MessageQueue 中。
- Looper 对象用来为一个线程开启一个消息循环,从而操作 MessageQueue;
默认情况下,Android 创建的线程没有开启消息循环,但是系统会自动为主线程创建 Looper 对象,开启消息循环;如果在子线程想要创建 Handler 对象,需要执行执行 Looper.prepare() 方法,然后创建 Handler 对象,最后执行 Looper.loop() 方法。
Looper.prepare();
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
}
}
Looper.loop();
3 Handler源码分析
Handler源码:
public class Handler {
final Looper mLooper;
final MessageQueue mQueue;
final Callback mCallback;
final boolean mAsynchronous;
/*
* 设置该标识为true用于检测继承Handler的非静态匿名,本地或者成员类出现内存泄漏的风险。
* /
private static final boolean FIND_POTENTIAL_LEAKS = false;
private static final String TAG = "Handler";
private static Handler MAIN_THREAD_HANDLER = null;
/**
* 实例化Handler的时候可以考虑使用该接口(Handler有这个类型的成员变量),避免必须继承实现Handler的抽象方法
* 该接口的handleMessage的返回值为true表示执行完该方法后,执行Handler的handleMessage方法;否则不执行Handler的handleMessage方法
*/
public interface Callback {
public boolean handleMessage(Message msg);
}
/**
* 子类必须重写该方法用于接收消息。
*/
public void handleMessage(Message msg) {
}
/**
* 处理消息的方法,Handler接收到的所有消息都会先被发送到这个方法中
* 通过该方法可以比较清楚的看到handler在接收到消息以后的处理顺序
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
/**
*默认构造方法,该方法在实际使用中,用的最多。
*/
public Handler() {
this(null, false);
}
/**
* 通过CallBack初始化
*/
public Handler(Callback callback) {
this(callback, false);
}
/**
* 使用指定的looper初始化Handler,构造方法在不指定Looper时,默认使用当前线程的Looper
*/
public Handler(Looper looper) {
this(looper, null, false);
}
/**
* 使用指定的looper和callback初始化Handler
*/
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
/**
*该构造方法中的参数决定是否以异步方式发出消息
* @hide
*/
public Handler(boolean async) {
this(null, async);
}
/**
* 该构造方法中IND_POTENTIAL_LEAKS,查询是否有内存泄漏的情况,如果存在会有日志打出
* 构造方法大多都会调用该构造方法,完成初始化
*/
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;
}
/**
* @hide
*/
内部方法不对外暴露
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
/** @hide */
@NonNull
内部方法不对外暴露,MAIN_THREAD_HANDLER是成员变量
public static Handler getMain() {
if (MAIN_THREAD_HANDLER == null) {
MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper());
}
return MAIN_THREAD_HANDLER;
}
/** @hide **/
@NonNull
内部方法不对外暴露
public static Handler mainIfNull(@Nullable Handler handler) {
return handler == null ? getMain() : handler;
}
/** {@hide} */
内部方法不对外暴露,简单的字符串组合之类的操作
public String getTraceName(Message message) {
final StringBuilder sb = new StringBuilder();
sb.append(getClass().getName()).append(": ");
if (message.callback != null) {
sb.append(message.callback.getClass().getName());
} else {
sb.append("#").append(message.what);
}
return sb.toString();
}
/**
* 返回一个消息对应的特殊字符串,具体字符串怎么组合出来的可以看以下源码
*/
public String getMessageName(Message message) {
if (message.callback != null) {
return message.callback.getClass().getName();
}
return "0x" + Integer.toHexString(message.what);
}
/**
* 以下方法均是从消息队列中获取消息的方法
*/
public final Message obtainMessage()
{
return Message.obtain(this);
}
public final Message obtainMessage(int what)
{
return Message.obtain(this, what);
}
public final Message obtainMessage(int what, Object obj)
{
return Message.obtain(this, what, obj);
}
public final Message obtainMessage(int what, int arg1, int arg2)
{
return Message.obtain(this, what, arg1, arg2);
}
public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
{
return Message.obtain(this, what, arg1, arg2, obj);
}
/**
* 把runnable加入的消息队列中去 ,该runnable中的操作将会在Handler所在的线程中执行
*/
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
/**
* 把runnable加入的消息队列中去 ,该runnable中的操作将会在Handler所在的线程中执行;其中参数uptimeMills指定了具体的什么时间执行该Runnable
*/
public final boolean postAtTime(Runnable r, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
/**
* 该方法相对于postAtTime(Runnable r, long uptimeMillis),多了一个token参数,这个参数命名有点误导的含义,其实就是message的object字段,该部分可以从getPostMessage(r, token)获知
*/
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
/**
* delayMills指定从当前时间开始以后的多少毫秒,执行r操作
*/
public final boolean postDelayed(Runnable r, long delayMillis)
{
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
/**
将消息发布到实现Runnable的对象,使Runnabler在下一次迭代中执行。 runnable将在此线程上运行处理程序。此方法适用于非常特殊的情况 ,它可以轻易地使消息队列饿死,导致排序问题,或者有其他意想不到的副作用。
*/
public final boolean postAtFrontOfQueue(Runnable r)
{
return sendMessageAtFrontOfQueue(getPostMessage(r));
}
/**
* timeout指定等待时间,runnable在等待指定时间以后会理解执行。不会在messageQueue中排队
* 这种方法很危险!使用不当可能导致死锁。在持有任何锁或在重复使用时,切勿调用此方法
*/
public final boolean runWithScissors(final Runnable r, long timeout) {
if (r == null) {
throw new IllegalArgumentException("runnable must not be null");
}
if (timeout < 0) {
throw new IllegalArgumentException("timeout must be non-negative");
}
if (Looper.myLooper() == mLooper) {
r.run();
return true;
}
BlockingRunnable br = new BlockingRunnable(r);
return br.postAndWait(this, timeout);
}
/**
*移除将要进行的操作
*/
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 boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
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);
}
/**
*立即把消息发送到消息队列,有点插队的意思,立即插到队列的最前部
*/
public final boolean sendMessageAtFrontOfQueue(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);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
//移除消息
public final void removeMessages(int what) {
mQueue.removeMessages(this, what, null);
}
public final void removeMessages(int what, Object object) {
mQueue.removeMessages(this, what, object);
}
public final void removeCallbacksAndMessages(Object token) {
mQueue.removeCallbacksAndMessages(this, token);
}
//检查是否包含某个消息
public final boolean hasMessages(int what) {
return mQueue.hasMessages(this, what, null);
}
public final boolean hasMessages(int what, Object object) {
return mQueue.hasMessages(this, what, object);
}
//检查handler是否有message或者callback
public final boolean hasMessagesOrCallbacks() {
return mQueue.hasMessages(this);
public final boolean hasCallbacks(Runnable r) {
return mQueue.hasMessages(this, r, null);
}
//获取handler对应的looper
public final Looper getLooper() {
return mLooper;
}
}