Home > Software engineering >  I can not stop a Runnable using Handler in JAVA
I can not stop a Runnable using Handler in JAVA

Time:01-17

I am trying to build a stopwatch and i have a button named start which starts the counting, after it starts the name of the button changes to stop and when i press stop i want to pause the counting, but when i am trying to run newHandler.removeCallbacks(updateTimerThread);the program continues counting, on the reset button this method works.

public class MainActivity extends AppCompatActivity {

    Button start_button, reset_button;
    TextView time_view;
    long start_time = 0, time_in_miliseconds = 0, update_time = 0, prev_time = 0;
    final Handler newHandler = new Handler();

    Runnable updateTimerThread = new Runnable() {
        @Override
        public void run() {
            time_in_miliseconds = SystemClock.uptimeMillis() - start_time;
            update_time = time_in_miliseconds   prev_time;
            int sec = (int) (update_time / 1000);
            int min = sec / 60;
            int hour = (int) sec / 3600;
            sec %= 60;
            int centisec = (int) (update_time / 10) % 100;
            time_view.setText("" hour ":" String.format("-",min) ":" String.format("-",sec) "." String.format("=",centisec));
            newHandler.postDelayed(this, 10);
            if (start_button.isPressed())
            {
                prev_time  = time_in_miliseconds;
                // Here the Runnable is not stopped 
                newHandler.removeCallbacks(updateTimerThread);
                //time_view.setText("" save_hour ":" String.format("-",save_min) ":" String.format("-",save_sec) "." String.format("=",save_centisec));
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        start_button = (Button) findViewById(R.id.start_button);
        reset_button = (Button) findViewById(R.id.reset_button);
        time_view = (TextView) findViewById(R.id.time_view);

        start_button.setOnClickListener(view -> {
            start_time = SystemClock.uptimeMillis();
            start_button.setText("Stop");
            newHandler.postDelayed(updateTimerThread,0);
        });
        if (start_button.isPressed())
        {
            prev_time  = time_in_miliseconds;
            newHandler.removeCallbacks(updateTimerThread);
            //time_view.setText("" save_hour ":" String.format("-",save_min) ":" String.format("-",save_sec) "." String.format("=",save_centisec));
        }
        reset_button.setOnClickListener(view -> {
            // Here the Runnable is stopped 
            newHandler.removeCallbacks(updateTimerThread);
            start_time = 0;
            prev_time = 0;
            time_view.setText("0:0:0.0");
            start_button.setText("Start");
        });
    }
}

CodePudding user response:

Please remove all conditions blocks where you are checking start_button.isPressed(), it doesn't work. You can use additional flag isRunning to indicate whether the clock is running or not:

private boolean isRunning;

start_button.setOnClickListener(view -> {
        if (isRunning) {
            newHandler.removeCallbacks(updateTimerThread);
            start_button.setText("Start");
        } else {
            start_time = SystemClock.uptimeMillis();
            start_button.setText("Stop");
            newHandler.post(updateTimerThread);
        }
        isRunning = !isRunning;
    });

CodePudding user response:

Your timer needs some state. You could do something like this (add 'boolean isActive'):

        Runnable updateTimerThread = new Runnable() {
            boolean isActive = true;
            @Override
            public void run() {
                if (isActive) {
                    time_in_miliseconds = SystemClock.uptimeMillis() - start_time;
                    update_time = time_in_miliseconds   prev_time;
                    // ...
                }
                if (start_button.isPressed()) {
                    isActive = !isActive;
                    // Do some other stuff
                }
            }
        };

Or maybe use the State Pattern.

  •  Tags:  
  • Related