Handler
Handler机制是Android中基于单线消息队列模式的一套线程消息机制。
Handler基础使用
子线程中创建Handler
Looper.prepare();//让线程与Looper关联
h = new Handler(Looper.myLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
}
};
Looper.loop();//不加则不能发送消息,启动循环
sendMessageAtTime以及sendMessageDelayed()区别
sendMessageDelayed()参数直接添加延迟多少毫秒,有sendMessageAtTime()源码分析可知延迟多少秒参数应为delayMillis+SystemClock.uptimeMillis();
原因:SystemClock.uptimeMillis()是获取系统从开机启动到现在的时间,期间不包括休眠的时间,这里获得到的时间是一个相对的时间,而不是通过获取当前的时间(绝对时间)。
而之所以使用这种方式来计算时间,而不是获得当前currenttime来计算,在于handler会受到阻塞,挂起状态,睡眠等,这些时候是不应该执行的;如果使用绝对时间的话,就会抢占资源来执行当前handler的内容,显然这是不应该出现的情况,所以要避免
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);//所有send方法都指向这个方法
}
sendMessageDelayed()源码:
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
消息机制原理
Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分在消息队列中逐一将消息取出,然后对消息进行处理,也就是发送消息和接收消息不是同步的处理。 这种机制通常用来处理相对耗时比较长的操作。
Handler通信四大类
Message源码分析
成员变量:
- public int what;//消息标识id
- public int arg1;//保存int数据
- public int arg2;//保存int数据
- public Object obj;//保存任意数据
- long when;//记录应该被处理的时间值
- Handler target;//用来处理消息的Handler对象,就是发送消息的handler,同样用来在Looper识别handler
- Runnable callback;//用来处理消息的回调器
- Message next;//指向下一个message用来形成一个链表
- private static Message sPool;//用来缓存处理过的Message,以便复用
- Message obtain();
Handler源码分析
sendMessage,postMessage:本质就是将消息添加到消息队列(MessageQueue.enqueueMessage())
Looper识别handler
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//会把this赋值给msg.target,此时target就指向当前Handler
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//之后调用MessageQueue的enqueueMessage分发消息进行处理
return queue.enqueueMessage(msg, uptimeMillis);
}
Lopper类源码分析
Looper.prepare():该方法在线程中将 Looper 对象定义为 ThreadLocal 对象,使得 Looper 对象成为该线程的私有对象,一个线程最多仅有一个 Looper。并在这个 Looper 对象中维护一个消息队列 MessageQueue 和持有当前线程的引用,因此 MessageQueue 也是线程私有。
Looper.loop():
public static void loop() {
// 得到当前线程的Looper对象
final Looper me = myLooper();
if (me == null) {
// 线程没有调用Looper.prepare(),所以没有Looper对象
throw new RuntimeException(
"No Looper; Looper.prepare() wasn't called on this thread.");
}
// 得到当前消息队列
final MessageQueue queue = me.mQueue;
...
// 开始循环
for (;;) {
// 从消息队列中获取下一个Message,该方法可以被阻塞
Message msg = queue.next();
...
// 将Message推送到Message中的target处理
// 此处的target就是发送该Message的Handler对象
msg.target.dispatchMessage(msg);
...
// 回收Message,这样就可以通过Message.obtain()复用
msg.recycleUnchecked();
}
}
MessageQueue(优先级队列),根据时间进行排序类源码分析
MessageQueue消息队列里面,添加的每一个消息都有对应的线程
1.插入消息到消息队列 2.唤醒Looper中等待的线程 (如果是及时消息并且线程是阻塞状态)
enqueueMessage源码分析:
boolean enqueueMessage(Message msg, long when) {
synchronized (this) {
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
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;
}
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}