Search code examples
javaandroidtimerandroid-handler

TimerTask not stopping after I click the stopbutton


So I click a start button and every second I change the text of a label with counting the time:

new CountDownTimer(30000, 500) {

    public void onTick(long millisUntilFinished) {

        if (zaciatokgotten) {

            T2 = new Timer();
            tt2 = new TimerTask() {

                public void run() {
                    if(stopclicked == true) {
                        this.cancel();
                    }
                    handler.post(new Runnable() {

                        public void run() {
                            hasStartedtt2 = true;
                            calendar = Calendar.getInstance();
                            simpledate = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
                            do_casu = simpledate.format(calendar.getTime());

                            zaciatok_hour = zaciatok.substring(11, 13);
                            zaciatok_minute = zaciatok.substring(14, 16);
                            koniec_hour = do_casu.substring(11, 13);
                            koniec_minute = do_casu.substring(14, 16);

                            zaciatok_sekundy = zaciatok.substring(17, 19);
                            koniec_sekundy = do_casu.substring(17, 19);


                            final_hour = ((Integer.parseInt(koniec_hour) - Integer.parseInt(zaciatok_hour)) );
                            final_minute = Integer.parseInt(koniec_minute) - Integer.parseInt(zaciatok_minute);
                            final_seconds = Integer.parseInt(koniec_sekundy) - Integer.parseInt(zaciatok_sekundy) - 1;


                            if (final_seconds < 0) {
                                final_seconds = final_seconds + 60;
                                final_minute = final_minute - 1;
                            }

                            if (final_minute < 0) {
                                final_hour = final_hour - 1;
                                final_minute = final_minute + 60;
                            }
                            if (final_hour < 0) {
                                final_hour = 0;
                            }
                            if (final_minute < 0) {
                                final_minute = 0;
                            }

                            if (final_hour == 0) {
                                if (final_minute == 0) {
                                    txtProgress.setText(final_seconds + " s");
                                } else {
                                    txtProgress.setText(final_minute + " m " + final_seconds + " s");
                                }
                            } else {
                                txtProgress.setText(final_hour + " h " + final_minute + " m " + final_seconds + " s");
                            }
                        }
                    });
                }
            };

            T2.schedule(tt2, 1000, 1000);

            if(once ==0) {
                new Thread(new Runnable() {

                    @Override
                    public void run() {

                        while (pStatus <= 100) {

                            handler.post(new Runnable() {

                                @Override
                                public void run() {
                                    progressBar.setProgress(pStatus);
                                }
                            });
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        pStatus++;
                        if (pStatus == 100) {
                            pStatus = 0;
                        }
                    }
                }
            }).start();

            once++;
            this.cancel();
        }
    }}

    public void onFinish() {
    }
}.start();

After I click the stop button the progressBar stops spinning, which is correct, but the time keeps incrementing, what am I doing wrong? Note that this issue is not present on the phones I used to test it, but its present on tablet devices, maybe they handle threads differently?

The code for stopping the timer here:

stopclicked = true
if(hasStartedtt2 == true) {
    tt2.cancel();
    //  handler.removeCallbacksAndMessages(null);
}
if (T2 != null) {
    T2.cancel();
    T2.purge();
}
pStatus = 101;

EDIT1: I just noticed it is stopped, but only 20 - 25 seconds after I clicked Stop, whats causing the delay?


Solution

  • The reason time won't stop (or stops "only 20 - 25 seconds after you clicked Stop") is the new instances of T2 = new Timer() and tt2 = new TimerTask() you create on every CountDownTimer's onTick(). The old instances of Timer and TimerTask keep residing on Java heap making their job until getting garbage-collected. You may notice the time changes being bumpy.

    Moreover, you seem to overcomplicate the task implementation. You might not need neither Timer nor TimerTask. The following example, that stops the time going, uses only CountDownTimer without Timer and TimerTask. I simplified the code a bit for the sake of brevity.

    private CountDownTimer timer;
    private TextView txtProgress;
    private Button stopButton;
    ...
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        txtProgress = findViewById(R.id.tv);
    
        timer = new CountDownTimer(30000, 500) {
    
            public void onTick(long millisUntilFinished) {
                        handler.post(() -> {
                            txtProgress.setText("any text");
                        });
            }
    
            public void onFinish() { }
    
        }.start();
    
        findViewById(R.id.stopButton).setOnClickListener(v -> timer.cancel());
    }