Handler postDelayed执行几次

时间:2017-10-22 18:19:35

标签: java android

我的UI上有一个SeekBar。当我改变它的位置时,我想在TextView中报告它的值。在这个TextView中,我还想提供一个信息,位置还有多长(以秒为单位)。我想,Runnable中的run方法只运行一次,但每次postDelayed执行时会运行几次。无论延迟是1秒还是10秒。如何强制它只运行一次?我应该制作一个帖子吗?

public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    y=0;
    myHandler.postDelayed(new Runnable(){
    @Override
    public void run(){
           myHandler.postDelayed(this, 1000);
           progressIndicator.setText("Covered: " + progressX.getProgress() + "/" + progressX.getMax() + " position is still for " + y + " seconds");
                    y+=1;
           }
    },1000);
}

编辑: removeCallbacks帮助了一下。代码工作正常,但只是在第一次进展时才改变,我明天会试着弄明白。

public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
  y=0;
  myHandler.postDelayed(new Runnable(){
           @Override
           public void run(){
           myHandler.removeCallbacks(this);
           y+=1;
           progressIndicator.setText("Covered: " + progressX.getProgress() + "/" + progressX.getMax() + " position is still for " + y + " seconds");
           myHandler.postDelayed(this, 5000);
           }
   },5000);
 }

3 个答案:

答案 0 :(得分:1)

问题是,每个事件 onProgressChanged 同时运行新的runnable。在运行方法中放置 myHandler.removeCallbacks(可运行),产生了一些积极的效果,它是唯一一个“正确”工作的地方。实际上, y 非常快,增加了我们之前和当前搜索栏位置的delta值( postDelayed 方法的累积),之后,它增加了每秒1。 removeCallbacks 杀死了之前的 postDelayed 操作。

public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            y=0;
            myHandler.postDelayed(new Runnable(){
                @Override
                public void run(){
                    myHandler.removeCallbacks(runnable);
                    ...
                    y+=1;
                    runnable=this;
                    myHandler.postDelayed(runnable, 1000);
                    }
            },1000);

然而,这是解决方案,将 myHandler.removeCallbacksAndMessages(null)放在 onProgressChanged 帮助中。 我附上代码以便更好地理解。 TextView progressIndicator 显示,您在搜索栏的当前位置停留多长时间(以秒为单位)。

public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            myHandler.removeCallbacksAndMessages(null);
            y=0;
            progressIndicator.setText("Covered: " + progressX.getProgress() + "/" +
                    progressX.getMax());
            myHandler.postDelayed(new Runnable(){
                @Override
                public void run(){
                    y+=1;
                    progressIndicator.setText("Covered: " + progressX.getProgress() + "/" +
                            progressX.getMax() + " position is still for " + y + " seconds");
                    runnable=this;
                    myHandler.postDelayed(runnable, 1000);

                }
            },1000);

答案 1 :(得分:0)

您基本上使用模式永远重复Runnable。在Runnable内,您可以拨打mHandler.postDelayed(this, 1000);。此上下文中的this是您最初创建的new Runnable。这意味着Runnable将在每次执行后一秒钟安排另一次运行。

如果您只想运行一次,则应该删除mHandler.postDelayed(this, 1000);行。

您还应确保在mHandler.removeCallbacks(null)中致电onDestroy(),以确保不会导致内存泄漏,因为Runnable将引用您的Activity通过TextView引用。

答案 2 :(得分:0)

移动搜索栏时会多次调用

onProgressChanged,这意味着您有几个待处理的postDelayed()

要解决此问题,每次拨打postDelayed()时,都应先拨打removeCallbacks(),以确保只有一个待处理的postDelayed()处于有效状态

但是你需要在类字段中创建Runnable和Handler实例,而不是在onProgressChanged主体上创建

这样的事情:

     private Handler myHandler = new Handler();
     private Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                // do something //
                myHandler.removeCallbacks(myRunnable);
                myHandler.postDelayed(myRunnable, 1000);
            }
        };




     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
         // do something //
         myHandler.removeCallbacks(myRunnable);
         myHandler.postDelayed(myRunnable, 1000);
}