Handler机制源码分析
1.Message
//Message:数据载体
public int what; //标识(id)
public int arg1; //保存int数据
public int arg2; //保存int数据
publib Object obj; //保存任意数据
long when; //记录应该被处理的时间值
Handler target; //用来处理消息的Handler对象,就是发送消息的handler
Runnable callback; //用来处理消息的回调器(一般不用)
Message next; //指向下一个message用来形成一个链表
private static Message sPool; //用来缓存处理过的Message,以便复用
Message obtain() //利用了Message中的消息池(sPool)
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
2.Handler
//Handler:发送消息、处理消息、移除消息
//发送消息
sendMessage(@NonNull Message msg)
sendMessageDelayed(msg, 0);
sendEmptyMessage(int what)
sendEmptyMessageDelayed(what, 0);
sendEmptyMessageDelayed(int what, long delayMillis)
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
sendMessageDelayed(@NonNull Message msg, long delayMillis)
if (delayMillis < 0) { //容错判断
delayMillis = 0;
}
sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis)
sendMessageAtTime(@NonNull Message msg, long uptimeMillis)
enqueueMessage(queue, msg, 0); //将消息添加到消息队列
enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,long uptimeMillis)
msg.target = this; //保存发送消息的Handler对象
queue.enqueueMessage(msg, uptimeMillis); //调用消息队列保存消息对象
//移除消息
removeMessages(int what) //移除消息
mQueue.removeMessages(this, what, null); //调用消息队列,移除它内部的指定what消息
//处理消息
handleMessage(@NonNull Message msg) //处理消息的回调方法
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) { //如果消息可以自己处理,让消息自己处理
handleCallback(msg);
} else {
if (mCallback != null) { //如果Handler对象中有回调监听器,调用回调器来处理
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg); //让Handler的handlerMessage()来处理
}
}
3.MessageQueue
//MessageQueue 存储消息的以Message的when排序优先级队列
enqueueMessage(Message msg, long when) //将Message添加到队列中
msg.when = when; //指定消息应该被处理的时间
for (;;) { //将当前消息对象保存到消息队列中的一个合适位置
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg; //最终结果:消息队列按when来排序的
nativeWake(mPtr); //通过本地方法实现对等待状态的底层线程
Message next() //取出一个合适的Message对象(可能不会立即返回)
nativePollOnce(ptr, nextPollTimeoutMillis); //本地方法,会导致可能处理等待状态,但不会阻塞线程
Message msg = mMessages; //取出消息队列中的第一个消息
return msg;
4.Looper
//Looper:从MessageQueue中获取当前需要处理的消息,并交给Handler处理
loop() //核心方法
final Looper me = myLooper(); //得到Looper对象
final MessageQueue queue = me.mQueue; //得到消息队列对象
for (;;) { //无限循环
Message msg = queue.next(); //从消息队列中取出消息(可能阻塞)
msg.target.dispatchMessage(msg); //调用Handler去分发并处理消息
msg.recycleUnchecked();//回收利用Message
}
Handler相关的一些问题
Handler 引起的内存泄露原因以及最佳解决方案
- 主线程的Looper对象的生命周期 = 该应用程序的生命周期
- 在Java中,非静态内部类 & 匿名内部类都默认持有外部类的引用
Handler 允许我们发送延时消息,如果在延时期间用户关闭了 Activity,那么该 Activity 会泄露。 这个泄露是因为 Message 会持有 Handler,而又因为 Java 的特性,内部类会持有外部类,使得 Activity 会被 Handler 持有,这样最终就导致 Activity 泄露。
解决:将 Handler 定义成静态的内部类,在内部持有 Activity 的弱引用,并在Acitivity的onDestroy()中调用handler.removeCallbacksAndMessages(null)及时移除所有消息。
为什么我们能在主线程直接使用 Handler,而不需要创建 Looper ?
通常我们认为 ActivityThread 就是主线程。事实上它并不是一个线程,而是主线程操作的管理者。在 ActivityThread.main() 方法中调用了 Looper.prepareMainLooper() 方法创建了 主线程的 Looper ,并且调用了 loop() 方法,所以我们就可以直接使用 Handler 了。
Handler里的 Callback 能干什么?
Handler.Callback 有优先处理消息的权利 ,当一条消息被 Callback 处理并拦截(返回 true),那么 Handler 的 handleMessage(msg) 方法就不会被调用了;如果 Callback 处理了消息,但是并没有拦截,那么就意味着一个消息可以同时被 Callback 以及 Handler 处理。