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中去了。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!