【问题标题】:Stop a stopwatch in Android在 Android 中停止秒表
【发布时间】:2014-11-25 06:20:16
【问题描述】:

我制作了一个自定义秒表,显示小时:分钟:秒。控件由 START 和 STOP 按钮提供。但是,停止秒表时出现问题。单击 STOP 按钮时它没有停止.任何人都请建议我正确的解决方案。

    package com.example.mystopwatch;


import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;


public class StopwatchActivity extends Activity {
private TextView textViewTimer;
private Button BtnStart,BtnStop;
private Handler mHandler = new Handler();
private long startTime;
private long elapsedTime;
private final int REFRESH_RATE = 100;
private String hours,minutes,seconds,milliseconds;
private long secs,mins,hrs,msecs;
private boolean stopped = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_stopwatch);
    BtnStart=(Button)findViewById(R.id.startbtn);
    BtnStop=(Button)findViewById(R.id.stopbtn);
    BtnStart.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
             Runnable startTimer1 = new Runnable() 
            { 
                public void run() 
                {
                    elapsedTime = System.currentTimeMillis() - startTime; updateTimer(elapsedTime);
                    mHandler.postDelayed(this,REFRESH_RATE); 
                    }


                };
             if(stopped)
             {
                 startTime = System.currentTimeMillis() - elapsedTime;
                 } 
             else
             { 
                 startTime = System.currentTimeMillis(); 
                 } 
             mHandler.removeCallbacks(startTimer1);
             mHandler.postDelayed(startTimer1, 0);


        }
                });
    BtnStop.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
             Runnable startTimer2 = new Runnable() 
                { 
                    public void run() 
                    {
                        elapsedTime = System.currentTimeMillis() - startTime; updateTimer(elapsedTime);
                        mHandler.postDelayed(this,REFRESH_RATE); 
                        }


                    };

            mHandler.removeCallbacks(startTimer2);
            stopped = true;

        }
    });

}   
private void updateTimer(long time) {
    // TODO Auto-generated method stub

        secs = (long)(time/1000); 
    mins = (long)((time/1000)/60);
    hrs = (long)(((time/1000)/60)/60); 
    secs = secs % 60; 
    seconds=String.valueOf(secs);
    if(secs == 0)
    { 
        seconds = "00";

    } 
    if(secs <10 && secs > 0)
    { 
        seconds = "0"+seconds; 
        }
    mins = mins % 60;
    minutes=String.valueOf(mins);
    if(mins == 0){ minutes = "00";
    } 
    if(mins <10 && mins > 0)
    {
        minutes = "0"+minutes;
        }
    hours=String.valueOf(hrs);
    if(hrs == 0)
    { 
        hours = "00";
        }
    if(hrs <10 && hrs > 0)
    {
        hours = "0"+hours;
        }
     milliseconds = String.valueOf((long)time);
     if(milliseconds.length()==2)
     {
         milliseconds = "0"+milliseconds;
         }
     if(milliseconds.length()<=1)
     { milliseconds = "00";
     } 
     milliseconds = milliseconds.substring(milliseconds.length()-3, milliseconds.length()-2); 
     ((TextView)findViewById(R.id.timertxt)).setText(hours + ":" + minutes + ":" + seconds);
     }
    }

【问题讨论】:

  • 你试过让 stopprd 变得易变吗?
  • volatile boolean stopped = false 你可以google一下。还有其他方法,但不知何故,您必须确保在检查的位置可以看到停止的 var 的更改。
  • 用火杀死它! :)

标签: java android multithreading button stopwatch


【解决方案1】:

BtnStop.setOnClickListener 中的大部分代码实际上是无用的。您定义了一个名为 startTimer2 的 Runnable,但目的是什么?除了在调用mHandler.removeCallbacks(startTimer2); 时,您永远不会使用该 Runnable。这将删除之前对其进行的所有调用,但由于您从未进行过任何调用,因此它不会执行任何操作。

当您单击停止按钮时,您的方法唯一要做的就是将布尔标志 stopped 设置为 true。但是没有定期检查该标志的过程。您检查标志的唯一时间是按下 START 按钮。

附带说明,您对REFRESH_RATE 的使用令人困惑。设置较高的数字实际上会导致较低的刷新率,因为 postDelayed 需要一段时间。考虑重命名变量或添加除法。

【讨论】:

    【解决方案2】:

    它不能停止,因为您没有在您的 run 方法中检查 boolean stopped。把它移到里面:

    public void run() {
        elapsedTime = System.currentTimeMillis() - startTime;
        updateTimer(elapsedTime);
        if(!stopped) {
            mHandler.postDelayed(this, REFRESH_RATE);
        }
    }
    

    并考虑根据 cmets 中的建议将已停止声明为 volatile

    【讨论】:

      【解决方案3】:

      整个任务开始和停止,秒表只需调用:-- handler.sendEmptyMessage(MSG_STOP_TIMER);停止秒表

      Handler handler = new Handler()
      {
          @Override
          public void handleMessage(Message msg) {
              super.handleMessage(msg);
              switch (msg.what) {
              case MSG_START_TIMER:
                  timer.start(); //start timer
      
                  handler.sendEmptyMessage(MSG_UPDATE_TIMER);
                  break;
      
              case MSG_UPDATE_TIMER:
                  //timerText.setText(String.format("%1$tM:%1$tS",timer.getElapsedTimeMin(),timer.getElapsedTimeSecs()));
                  if ( timer.getElapsedTimeSecs() < 10)
                  {
                      if(timer.getElapsedTimeMin()<10){
                          timerText.setText("0" + timer.getElapsedTimeMin() + ":0" + timer.getElapsedTimeSecs());
                      }else{
                          timerText.setText("" + timer.getElapsedTimeMin() + ":0" + timer.getElapsedTimeSecs());  
                      }
                  }
                  else{
                      if(timer.getElapsedTimeMin()<10){
                          timerText.setText("0" + timer.getElapsedTimeMin() + ":" + timer.getElapsedTimeSecs());
                      }else{
                          timerText.setText(timer.getElapsedTimeMin()+":"+ timer.getElapsedTimeSecs());  
                      }
      
                  }
                  handler.sendEmptyMessageDelayed(MSG_UPDATE_TIMER,REFRESH_RATE); //text view is updated every second,
                  break;                                  //though the timer is still running
              case MSG_STOP_TIMER:
                  handler.removeMessages(MSG_UPDATE_TIMER); // no more updates.
                  timer.stop();//stop timer
                  timerText.setText("0"+timer.getElapsedTimeMin()+":0"+ timer.getElapsedTimeSecs());
                  break;
      
              default:
                  break;
              }
          }
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-18
        • 2019-01-05
        • 2020-04-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多