您好,欢迎访问一九零五行业门户网

Java Handler同步屏障实例代码分析

1.在view的加载和绘制流程中,有一个编舞者类,mchoreographer。 
mtraversalbarrier = mhandler.getlooper().postsyncbarrier();向messagequeue中插入一条同步屏障消息,msg.target==null的消息,返回值mtraversalbarrier是一个int 的token值。
void scheduletraversals() { if (!mtraversalscheduled) { mtraversalscheduled = true; //向消息队列插入一个同步屏障的消息。msg.target==null的消息 mtraversalbarrier = mhandler.getlooper().postsyncbarrier(); mchoreographer.postcallback( choreographer.callback_traversal, mtraversalrunnable, null); } }
mchoreographer.postcallback()方法会执行mtraversalrunnable中的代码。
mhandler.getlooper().removesyncbarrier(mtraversalbarrier);这个会根据上面产生的token值移出messagequeue中的同步屏障消息。
final traversalrunnable mtraversalrunnable = new traversalrunnable(); final class traversalrunnable implements runnable { @override public void run() { dotraversal(); } } void dotraversal() { if (mtraversalscheduled) { mtraversalscheduled = false; //移除同步屏障消息 mhandler.getlooper().removesyncbarrier(mtraversalbarrier); //在这个方法中会调用 measure layout draw,view的绘制绘制流程的方法 performtraversals(); } }
还是看这行代码mhandler.getlooper().postsyncbarrier(),系统是怎么处理的。
获取了一个没有设置handler的message。
int enqueuesyncbarrier(long when) { // enqueue a new sync barrier token. // we don't need to wake the queue because the purpose of a barrier is to stall it. synchronized (this) { final int token = mnextbarriertoken++; // 这个msg.target没有被赋值 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) { // invariant: p == prev.next msg.next = p; prev.next = msg; } else { msg.next = p; mmessages = msg; } return token; } }
正常我们通过handler发送消息,handler是不允许为空的。
boolean enqueuemessage(message msg, long when) { if (msg.target == null) { throw new illegalargumentexception("message must have a target."); } ...........}
那系统为啥要发送一个handler为空的消息呢?
先看mchoreographer发了同步屏障消息后,又做了什么?
又发送了一个异步消息:msg.setasynchronous(true),这个消息的handler不为null。
private void postcallbackdelayedinternal(int callbacktype, object action, object token, long delaymillis) { synchronized (mlock) { final long now = systemclock.uptimemillis(); final long duetime = now + delaymillis; mcallbackqueues[callbacktype].addcallbacklocked(duetime, action, token); if (duetime <= now) { scheduleframelocked(now); } else { message msg = mhandler.obtainmessage(msg_do_schedule_callback, action); msg.arg1 = callbacktype; //将消息设置为异步消息 msg.setasynchronous(true); mhandler.sendmessageattime(msg, duetime); } }}
接下来看看messagequeue是怎么去消息的,是如何对这个同步屏障消息怎么处理的。
message next() { synchronized (this) { // try to retrieve the next message. return if found. final long now = systemclock.uptimemillis(); message prevmsg = null; message msg = mmessages; //如果msg.target==null说明我们已经向消息队里中插入了一条屏障消息。 //此时会进入到这个循环中,找到msg.isasynchronous==true的异步消息。 //通常我们发送的都是同步消息isasynchronous = false的,并且msg.target不能为null的。 if (msg != null && msg.target == null) { // stalled by a barrier. find the next asynchronous message in the queue. do { prevmsg = msg; msg = msg.next; } while (msg != null && !msg.isasynchronous());//msg.isasynchronous==true时结束循环,说明找到了这个异步消息。 } if (msg != null) {//找到了同步屏障的异步消息后,直接返回 if (now < msg.when) { // next message is not ready. set a timeout to wake up when it is ready. nextpolltimeoutmillis = (int) math.min(msg.when - now, integer.max_value); } else { // got a message. mblocked = false; if (prevmsg != null) { prevmsg.next = msg.next; } else { mmessages = msg.next; } msg.next = null; if (false) log.v("messagequeue", "returning message: " + msg); return msg; } } else {//没有找到的话则进入休眠直到下一次被唤醒 // no more messages. nextpolltimeoutmillis = -1; } } }
在取消的时候,先判断进行msg.target为null的判断,然后经过while循环,找到msg.isasynchronous() == true的消息。也就是上面发送的异步消息。通常我们发送的消息都是同步消息,不会对对 msg.setasynchronous(true);进行设置。
系统这样做的目的就是为了优先去处理这个异步消息。会把所有的同步消息放在后面,向一道屏障一样,所以这样的操作,被称为同步屏障,是同步屏障消息的处理有更高的优先级。
因为编舞者类mchoreographer 负责屏幕的渲染,需要及时的处理从底层过来的信号,以保障界面刷新的频率。
以上就是java handler同步屏障实例代码分析的详细内容。
其它类似信息

推荐信息