Android Handler移除Message详解及实例代码
AndroidHandler移除Message详解
问题:
1.removeMessage(what)函数是否只能移除对应what值的Message?
2.对于Delayed发送的Message,能否提前remove?
代码测试:
packagejavine.k.testhandler; importandroid.app.Activity; importandroid.os.Bundle; importandroid.os.Handler; importandroid.os.HandlerThread; importandroid.os.Message; importandroid.util.Log; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassTestHandlerActivityextendsActivityimplementsOnClickListener{ privateButtonstartBtn; privateButtonendBtn; publicHandlerthreadHandler;//子线程Handler privateHandlermHandler=newHandler(){ publicvoidhandleMessage(android.os.Messagemsg){ threadHandler.sendEmptyMessageDelayed(1,2000); Log.d("info","handlemain-threadmessage..."); }; }; @Override protectedvoidonCreate(BundlesavedInstanceState){ //TODOAuto-generatedmethodstub 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); newThread(newRunnable(){ @Override publicvoidrun(){ HandlerThreadhandlerThread=newHandlerThread("handler"); handlerThread.start(); threadHandler=newHandler(handlerThread.getLooper()){ @Override publicvoidhandleMessage(Messagemsg){ //mHandler.sendEmptyMessageDelayed(0,2000);<spanstyle="font-family:Arial,Helvetica,sans-serif;"></span>
<spanstyle="white-space:pre"></span><prename="code"class="java"><spanstyle="white-space:pre"></span>mHandler.sendEmptyMessageDelayed(1,2000);
Log.d("info","handlesub-threadmessage...");}};}}).start();}@OverridepublicvoidonClick(Viewv) {//TODOAuto-generatedmethodstubswitch(v.getId()){caseR.id.startButton: //开始发送消息mHandler.sendEmptyMessage(1);break;caseR.id.endButton: //移除主线程Handler的消息mHandler.removeMessages(1);break;default:break;}}}
测试结果:
1.removeMassage(1)无法移除what=0的Message。
2.在子线程中执行完
<span></span><prename="code"class="java"><spanstyle="white-space:pre"> </span>mHandler.sendEmptyMessageDelayed(1,2000);
Log.d("info","handlesub-threadmessage...");
之后,即可通过removeMesage(1)来移除消息,mHandler将不能接收到该条消息。
源码分析:
1.Android如何移除一条Message?
查看源码可知,Handler.removeMessage(intwhat)内部调用MessageQueue.removeMessage(this,what,null)
查看MessageQueue的removeMessage方法如下:
voidremoveMessages(Handlerh,intwhat,Objectobject){ if(h==null){ return; } synchronized(this){ Messagep=mMessages; //Removeallmessagesatfront. while(p!=null&&p.target==h&&p.what==what &&(object==null||p.obj==object)){ Messagen=p.next; mMessages=n; p.recycle(); p=n; } //Removeallmessagesafterfront. while(p!=null){ Messagen=p.next; if(n!=null){ if(n.target==h&&n.what==what &&(object==null||n.obj==object)){ Messagenn=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,源码如下:
booleanenqueueMessage(Messagemsg,longwhen){ if(msg.isInUse()){ thrownewAndroidRuntimeException(msg+"Thismessageisalreadyinuse."); } if(msg.target==null){ thrownewAndroidRuntimeException("Messagemusthaveatarget."); } synchronized(this){ if(mQuitting){ RuntimeExceptione=newRuntimeException( msg.target+"sendingmessagetoaHandleronadeadthread"); Log.w("MessageQueue",e.getMessage(),e); returnfalse; } msg.when=when; Messagep=mMessages; booleanneedWake; if(p==null||when==0||when<p.when){ //Newhead,wakeuptheeventqueueifblocked. msg.next=p; mMessages=msg; needWake=mBlocked; }else{ //Insertedwithinthemiddleofthequeue.Usuallywedon'thavetowake //uptheeventqueueunlessthereisabarrierattheheadofthequeue //andthemessageistheearliestasynchronousmessageinthequeue. needWake=mBlocked&&p.target==null&&msg.isAsynchronous(); Messageprev; 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; } //WecanassumemPtr!=0becausemQuittingisfalse. if(needWake){ nativeWake(mPtr); } } returntrue; }
由上可知:MessageQueue会对需要延迟发送的Message排序,按照需要延迟的时间长短(when)。
即,虽然是延迟发送的消息,其实当你调用发送函数之后,Message就已经被添加到MessageQueue中去了。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!