Mark023 Mark023 - 4 months ago 12
Java Question

how to stop scheduled timer after dialog is closed

I have a scheduled timer running to show the delay in coming to school. Whenever a student arrives to the school, a custom dialog opens up with display showing the

delay in arrival : 20.0 min
. It gets incremented by
0.5min
every half a minute. My code is -

public void startTimer(long delay_minutes) {
final long delay = delay_minutes;
delay_countup = (double) delay;

//Start the scheduled time
departuretimer = new Timer();
departuretimer.scheduleAtFixedRate(new TimerTask() {
public void run() {
countup = 0.0 + delay_countup;
Log.d("hi","Values 0" + delay_countup + countup);
mHandler.obtainMessage(1).sendToTarget();
delay_countup = delay_countup + 0.5;
Log.d("hi","Values 1" + delay_countup);
}
}, 0, 30000);
}

public Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
delay_time.setText(String.valueOf(countup) + "min");
rootView.invalidate();
}
};


The problems are -

a) the timer runs in background for the old arrived student even when the dialog is opened for new arrived student. I mean the timer is never killed when the dialog is closed.(The dialog is closed only to confirm the arrival of the student)

b) Sometimes the textview
delay_time
displays wrong value. It shows
22.0min
and immediately
0.5min
and then again
23.0min
.

Why is this?

EDIT 1:
Handling
timer cancel
after click of button in the dialog

private void handleClickAction() {
dismiss();
timer.cancel();
timer = null;
}


EDIT 2 :
The logs always display correct values but in the UI sometimes there is a problem. The problem is that for example -

delay_countup = 50.0
countup = 50.0
Textview updates as 50.0 //This is correct

Now,
delay_countup = 50.5
countup = 50.5
Textview updates as 0.5 //This is incorrect. I need 50.5

Answer

It seems that you are never removing the first timer. So when you initialize the second timer you have two timers simultaneously trying to update the UI.

Store the timer as a member variable and check if it's initialized before starting a second one. When the dialog is closed you should cancel() the Timer. So you should also see how to implement methods when the dialog is dismissed - this should call a cleanup method which cancel() and sets the timer to null.

public class DialogTest extends Dialog {

    Timer timer;
    double countup = 0;
    double initial_time = 0;

    public DialogTest(Context context){
        super(context);

    }


    @Override
    protected void onStart() {
        super.onStart();

        startUpCounting();
    }

    @Override
    protected void onStop() {
        Log.e("b", "timer stopped");
        if(timer != null){
            timer.cancel();
            timer = null;
        }

        super.onStop();
    }

    public void startUpCounting() {
        delay_for_student.setText("Delay in Arrival");
        rootView.invalidate();
        Log.e("b", "timer started");
        if(timer != null){
            timer.cancel();
            timer = null;
        }
        timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            public void run() {
                countup = 0.0 + initial_time;
                if (countup == 0.0) {
                    onTimeHandler.obtainMessage(1).sendToTarget();
                } else {
                    mHandler.obtainMessage(1).sendToTarget();
                }
                initial_time = initial_time + 0.5;
            }
        }, 0, 1000);
    }



    public Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            Log.e("b", "timer: " + countup);
            delay_time.setText(String.valueOf(countup) + "min");
            rootView.invalidate();
        }
    };

    public Handler onTimeHandler = new Handler() {
        public void handleMessage(Message msg) {
            Log.e("b", "timer ---");
            delay_time.setText("-");
            rootView.invalidate();
        }
    };
}