Handler原理简述
只做简单概述,具体详细细节可查看相关源码
1.handler发送消息根据时间先后顺序插入到消息队列
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
2.Looper.loop()不断从消息队列中取消息
for (;;) {
Message msg = queue.next();
if (msg == null) {
return;
}
...
...
msg.target.dispatchMessage(msg);
...
...
}
}
3.MessageQueue.next() 取消息,重点分析
Message next() {
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1;
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
nextPollTimeoutMillis = -1;
}
····
····
}
}
4.简单总结一下
1.消息队列中可存放三种消息,屏障消息(msg.target == null),异步消息(msg.isAsynchronous()= true),同步消息(msg.isAsynchronous()= false)
2.如果消息头不是屏障消息,则异步消息和同步消息没有区别,消息队列头会后移
3.如果消息头是屏障消息,则只能通过异步消息,不能通过同步消息,消息队列头不会后移,只能手动移除
发送三种消息
1.发送普通消息,当然handler可指定默认消息类型
public Handler(boolean async) {
this(null, async);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
val obtainMessage = handler.obtainMessage().apply {
what = 1
isAsynchronous = false
obj = "普通消息”
}
handler.sendMessageDelayed(obtainMessage, time)
2.发送异步消息
val obtainMessage = handler.obtainMessage().apply {
what = 2
isAsynchronous = true
obj = "异步消息”
}
handler.sendMessageDelayed(obtainMessage, time)
3.发送屏障消息,同步异步消息只有在遇到屏障头消息时才有效,查看源码
@TestApi
public int postSyncBarrier() {
return postSyncBarrier(SystemClock.uptimeMillis());
}
private int postSyncBarrier(long when) {
synchronized (this) {
final int token = mNextBarrierToken++;
final Message msg = Message.obtain();
msg.markInUse();
msg.when = when;
msg.arg1 = token;
Message prev = null;
Message p = mMessages;
if (when != 0) {
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
}
if (prev != null) {
msg.next = p;
prev.next = msg;
} else {
msg.next = p;
mMessages = msg;
}
return token;
}
}
4.发送屏障消息,反射调用
private val postSyncBarrier = MessageQueue::class.java.getDeclaredMethod("postSyncBarrier", Long::class.java).apply {
isAccessible = true
}
private val removeSyncBarrier = MessageQueue::class.java.getDeclaredMethod("removeSyncBarrier", Int::class.java).apply {
isAccessible = true
}
使用Demo
private val handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
Log.d(TAG, "handleMessage:-${msg.what}--${msg.isAsynchronous}-- ${msg.obj}--${msg.`when`}")
when (msg.what) {
0 -> {
removeSyncBarrier.invoke(queue, msg.g1)
}
}
}
}
private val queue = handler.looper.queue
private val postSyncBarrier = MessageQueue::class.java.getDeclaredMethod("postSyncBarrier", Long::class.java).apply {
isAccessible = true
}
private val removeSyncBarrier = MessageQueue::class.java.getDeclaredMethod("removeSyncBarrier", Int::class.java).apply {
isAccessible = true
}
private fun senMsg(handler: Handler, w: Int, async: Boolean, str: String, time: Long, arg: Int = 0) {
val obtainMessage = handler.obtainMessage().apply {
what = w
arg1 = arg
isAsynchronous = async
obj = str
}
handler.sendMessageDelayed(obtainMessage, time)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
senMsg(handler, 1, false, "同步消息", 1000)
val token = postSyncBarrier.invoke(queue, SystemClock.uptimeMillis() + 2000)
senMsg(handler, 2, false, "同步消息", 3000)
senMsg(handler, 3, false, "同步消息", 4000)
senMsg(handler, 4, true, "isAsynchronous 异步消息 ", 5000)
senMsg(handler, 5, false, "同步消息", 6000)
senMsg(handler, 6, true, "isAsynchronous 异步消息", 7000)
senMsg(handler, 7, false, "同步消息", 8000)
senMsg(handler, 8, true, "isAsynchronous 异步消息", 9000)
senMsg(handler, 0, true, "isAsynchronous 移除屏障", 9000, token as Int)
senMsg(handler, 9, false, "同步消息", 10 * 1000)
senMsg(handler, 10, false, "同步消息", 11 * 1000)
senMsg(handler, 11, true, "isAsynchronous 异步消息", 12 * 1000)
senMsg(handler, 12, false, "同步消息", 13 * 1000)
senMsg(handler, 13, false, "同步消息", 14 * 1000)
senMsg(handler, 11, true, "isAsynchronous 异步消息", 15 * 1000)
}
测试结果
19:54:37.854 : handleMessage:-1--false-- 同步消息--11075427
19:54:41.857 : handleMessage:-4--true-- isAsynchronous 异步消息 --11079427
19:54:43.855 : handleMessage:-6--true-- isAsynchronous 异步消息--11081427
19:54:45.855 : handleMessage:-8--true-- isAsynchronous 异步消息--11083427
19:54:45.855 : handleMessage:-0--true-- isAsynchronous 移除屏障--11083427
19:54:45.855 : handleMessage:-2--false-- 同步消息--11077427
19:54:45.856 : handleMessage:-3--false-- 同步消息--11078427
19:54:45.856 : handleMessage:-5--false-- 同步消息--11080427
19:54:45.856 : handleMessage:-7--false-- 同步消息--11082427
19:54:46.854 : handleMessage:-9--false-- 同步消息--11084427
19:54:47.854 : handleMessage:-10--false-- 同步消息--11085427
19:54:48.854 : handleMessage:-11--true-- isAsynchronous 异步消息--11086427
19:54:49.854 : handleMessage:-12--false-- 同步消息--11087427
19:54:50.855 : handleMessage:-13--false-- 同步消息--11088428
19:54:51.855 : handleMessage:-11--true-- isAsynchronous 异步消息--11089428