欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android Handler移除Message详解及实例代码

程序员文章站 2023-12-14 15:35:28
android handler移除message详解 问题: 1.removemessage(what)函数是否只能移除对应what值的message? 2.对于de...

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中去了。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

上一篇:

下一篇: