Android Handler移除Message详解及实例代码
android handler移除message详解
问题:
1.removemessage(what)函数是否只能移除对应what值的message?
2.对于delayed发送的message,能否提前remove?
代码测试:
package javine.k.testhandler; import android.app.activity; import android.os.bundle; import android.os.handler; import android.os.handlerthread; import android.os.message; import android.util.log; import android.view.view; import android.view.view.onclicklistener; import android.widget.button; public class testhandleractivity extends activity implements onclicklistener { private button startbtn; private button endbtn; public handler threadhandler; //子线程handler private handler mhandler = new handler() { public void handlemessage(android.os.message msg) { threadhandler.sendemptymessagedelayed(1, 2000); log.d("info", "handle main-thread message..."); }; }; @override protected void oncreate(bundle savedinstancestate) { // todo auto-generated method stub super.oncreate(savedinstancestate); setcontentview(r.layout.main); startbtn = (button) findviewbyid(r.id.startbutton); endbtn = (button) findviewbyid(r.id.endbutton); startbtn.setonclicklistener(this); endbtn.setonclicklistener(this); new thread(new runnable() { @override public void run() { handlerthread handlerthread = new handlerthread("handler"); handlerthread.start(); threadhandler = new handler(handlerthread.getlooper()) { @override public void handlemessage(message msg) { //mhandler.sendemptymessagedelayed(0, 2000);<span style="font-family: arial, helvetica, sans-serif;"> </span>
<span style="white-space:pre"></span><pre name="code" class="java"><span style="white-space:pre"> </span>mhandler.sendemptymessagedelayed(1, 2000);
log.d("info", "handle sub-thread message...");}};}}).start();}@overridepublic void onclick(view v) {// todo auto-generated method stubswitch (v.getid()) {case r.id.startbutton: //开始发送消息mhandler.sendemptymessage(1);break;case r.id.endbutton: //移除主线程handler的消息mhandler.removemessages(1);break;default:break;}}}
测试结果:
1. removemassage(1)无法移除what=0的message。
2. 在子线程中执行完
<span></span><pre name="code" class="java"><span style="white-space:pre"> </span>mhandler.sendemptymessagedelayed(1, 2000);
log.d("info", "handle sub-thread message...");
之后,即可通过removemesage(1)来移除消息,mhandler将不能接收到该条消息。
源码分析:
1.android如何移除一条message?
查看源码可知,handler.removemessage(int what)内部调用messagequeue.removemessage(this, what, null)
查看messagequeue的removemessage方法如下:
void removemessages(handler h, int what, object object) { if (h == null) { return; } synchronized (this) { message p = mmessages; // remove all messages at front. while (p != null && p.target == h && p.what == what && (object == null || p.obj == object)) { message n = p.next; mmessages = n; p.recycle(); p = n; } // remove all messages after front. while (p != null) { message n = p.next; if (n != null) { if (n.target == h && n.what == what && (object == null || n.obj == object)) { message nn = n.next; n.recycle(); p.next = nn; continue; } } p = n; } } }
筛选要移除的message的条件是:target(handler),what,object
该函数分两步来移除message:
1).移除在前端的符合条件的message
2).移除后面的符合条件的message
2.为何延迟发送的message在延迟时间到达之前就可以被移除?
handler.sendemptymessagedelayed() ---调用---> sendmessageattime() -----调用---> enqueuemessage() ----调用messagequeue.enqueuemessage()
实际进行处理的就是messagequeue,源码如下:
boolean enqueuemessage(message msg, long when) { if (msg.isinuse()) { throw new androidruntimeexception(msg + " this message is already in use."); } if (msg.target == null) { throw new androidruntimeexception("message must have a target."); } synchronized (this) { if (mquitting) { runtimeexception e = new runtimeexception( msg.target + " sending message to a handler on a dead thread"); log.w("messagequeue", e.getmessage(), e); return false; } msg.when = when; message p = mmessages; boolean needwake; if (p == null || when == 0 || when < p.when) { // new head, wake up the event queue if blocked. msg.next = p; mmessages = msg; needwake = mblocked; } else { // inserted within the middle of the queue. usually we don't have to wake // up the event queue unless there is a barrier at the head of the queue // and the message is the earliest asynchronous message in the queue. 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; } // we can assume mptr != 0 because mquitting is false. if (needwake) { nativewake(mptr); } } return true; }
由上可知:messagequeue会对需要延迟发送的message排序,按照需要延迟的时间长短(when)。
即,虽然是延迟发送的消息,其实当你调用发送函数之后,message就已经被添加到messagequeue中去了。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!