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

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

(0)

相关推荐

  • android handler.post和handler.sendMessage的区别和联系

    现在大部分人都很熟悉handler这个东西了,我们常用handler的场景无非有两个: 1. 异步更新UI 2. 延时任务 但是我一直有一个困惑,就是handler.post(r)这个方法有什么独特的作用? 通过看源码发现,post这个方法是把任务r转成一个message放进了handler所在的线程中的messageQueue消息队列中,并且是立刻发送的消息,这样它既不是异步的也不是延时的,所以问题来了: 1. 它和sendMessage()有什么区别? 2. 它有什么独特作用呢? 下结论之前

  • Android计时器的三种实现方式(Chronometer、Timer、handler)

    本文实例为大家分享了Android计时器的三种方法,具体内容如下 目录: 1.借助Timer实现 2.调用handler.sendMessagedely(Message msg, long delayMillis) 3.借助布局Chronometer 1.借助Timer实现 (1) 布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http:/

  • Android 消息机制以及handler的内存泄露

    Handler 每个初学Android开发的都绕不开Handler这个"坎",为什么说是个坎呢,首先这是Android架构的精髓之一,其次大部分人都是知其然却不知其所以然.今天看到Handler.post这个方法之后决定再去翻翻源代码梳理一下Handler的实现机制. 异步更新UI 先来一个必背口诀"主线程不做耗时操作,子线程不更新UI",这个规定应该是初学必知的,那要怎么来解决口诀里的问题呢,这时候Handler就出现在我们面前了(AsyncTask也行,不过本质

  • Android 优化Handler防止内存泄露

    Android 优化Handler防止内存泄露 Demo描述: Handler可能导致的内存泄露及其优化 1 关于常见的Handler的用法但是可能导致内存泄露 2 优化方式请参考BetterHandler和BetterRunnable的实现 package cc.cc; import java.lang.ref.WeakReference; import android.os.Bundle; import android.os.Handler; import android.os.Messag

  • Android HandlerThread的使用及原理详解

    一.HandlerThread的含义 HandlerThread能够新建拥有Looper的线程.这个Looper能够用来新建其他的Handler.(线程中的Looper)需要注意的是,新建的时候需要被回调. 二.HandlerThread的用法 一般情况下,我们会经常用Handler在子线程中更新UI线程,那是因为在主线程中有Looper循环,而HandlerThread新建拥有Looper的子线程又有什么用呢? 必然是执行耗时操作.举个例子,数据实时更新,我们每10秒需要切换一下显示的数据,如

  • 解决Android使用Handler造成内存泄露问题

    一.什么是内存泄露? Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引用所指向,则该对象会在被GC发现的时候被回收:另外,如果一组对象中只包含互相的引用,而没有来自它们外部的引用(例如有两个对象A和B互相持有引用,但没有任何外部对象持有指向A或B的引用),这仍然属于不可到达,同样会被GC回收. Android中使用Handler造成内存泄露的原因 private Han

  • Android中Handler与Message的简单实例

    Android中Handler与Message的简单实例 前言: 虽然笔者已经学习了Android的AsyncTask来实现一部消息的处理.但是在android的学习中,经常会在一些demo中看到Handler与Message的一些使用,所以Handler与Message的学习也是有必要了.至于学多少,笔者还是比较坚持自己的看法,"用多少,学多少",毕竟已经有了AsyncTask如此方便的东西,Handler与Message也不是那么必不可缺了.(如此文的简单了解一下还是不需要花太多时

  • 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.Han

  • Android LayoutInflater加载布局详解及实例代码

    Android  LayoutInflater加载布局详解 对于有一定Android开发经验的同学来说,一定使用过LayoutInflater.inflater()来加载布局文件,但并不一定去深究过它的原理,比如 1.LayoutInflater为什么可以加载layout文件? 2.加载layout文件之后,又是怎么变成供我们使用的View的? 3.我们定义View的时候,如果需要在布局中使用,则必须实现带AttributeSet参数的构造方法,这又是为什么呢? 既然在这篇文章提出来,那说明这三

  • Android 活动条ActionBar的详解及实例代码

    Android 活动条ActionBar的详解 图一 图二 图三 图四 图五 ActionBar其提供的功能总结 图一使用ActionBar显示选项菜单项 menu_mainxml代码 启用程序图标导航 如何添加Action View 图二Activity代码区 menu_mainxml代码 clockxml 图三使用ActionBar实现Tab导航 创建ActionBar实现Tab导航步骤 MainActivity代码 DummyFragmentjava代码 图四Android 30之前的Fr

  • Android ListView 滚动条的设置详解及实例代码

    Android ListView 滚动条的设置详解 1.滚动条的属性 android:scrollbarAlwaysDrawHorizontalTrack 设置是否始终显示水平滚动条.这里用ScrollView.ListView测试均没有效果. android:scrollbarAlwaysDrawVerticalTrack 设置是否始终显示垂直滚动条.这里用ScrollView.ListView测试均没有效果. android:scrollbarDefaultDelayBeforeFade 设

  • Android 欢迎全屏图片详解及实例代码

    Android 欢迎全屏图片详解 其实欢迎界面就是在主Activity之前再添加一个欢迎的Activity.在这个Activity中实现欢迎界面,和其他的Activity用法 是基本一样,只有细微的差别.     1.在Activity的onCreate方法中实现: @Override ic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /**全屏设置,隐藏窗口所有装饰**/ getW

  • Android  LayoutInflater加载布局详解及实例代码

    Android  LayoutInflater加载布局详解 对于有一定Android开发经验的同学来说,一定使用过LayoutInflater.inflater()来加载布局文件,但并不一定去深究过它的原理,比如 1.LayoutInflater为什么可以加载layout文件? 2.加载layout文件之后,又是怎么变成供我们使用的View的? 3.我们定义View的时候,如果需要在布局中使用,则必须实现带AttributeSet参数的构造方法,这又是为什么呢? 既然在这篇文章提出来,那说明这三

  • Android Dialog详解及实例代码

     Android Dialog详解及实例代码 概述: Android开发中最常用的就是Dialog类,除了自定义dialog布局,最多的就是用在弹出对话框.进度条.输入框.单选.复选框. 1.选择对话框: AlertDialog.Builder dialog = new AlertDialog.Builder(this); dialog.setTitle("选择对话框"); dialog.setMessage("请选择确认或取消"); dialog.setCance

  • Android获取分享应用列表详解及实例

    Android获取分享应用列表详解及实例 如果在应用的AndroidManifest.xml中含有 ACTION_SEND 属性,那就证明该应用可以供第三方应用进行调用分享,那怎么获取函数该属性的分享列表了,这对我们做应用的非常有用:最近在做该功能,自己也做了下自定义的分享列表,用PopupWindow的方式弹出. 1.布局: popup_share.xml <?xml version="1.0" encoding="utf-8"?> <Linea

  • Android 列表选择框 Spinner详解及实例

    Android 列表选择框 Spinner详解及实例 Spinner 是 Android 的列表选择框,不过 spinner 并不需要显示下拉列表,而是相当于弹出一个菜单供用户选择. Spinner 属性: ● android:spinnerMode:列表显示的模式,有两个选择,为弹出列表(dialog)以及下拉列表(dropdown),如果不特别设置,为下拉列表. ● android:entries:使用<string-array.../>资源配置数据源. ● android:prompt:

  • Android ViewPagerIndicator详解及实例代码

    Android ViewPagerIndicator详解及实例代码 关于自定义View的属性零碎知识 自定义View和自定义属性的知识不再此提及,这里着重说的是属性在自定义View中的获取方式,自定义的属性如下: <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="Wisely"> <attr name=&

随机推荐