Android CountDownTimer - last onTick not called - which clean solution to use?

post frustration ....

I just stumbled upon the problem "CountDownTimer - last onTick not called", which many have reported here.

Simple problem demonstration

package com.example.gosh;

import android.app.Activity;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.util.Log;

public class CountDownTimerSucksActivity extends Activity {

int iDontWantThis = 0; // choose 100 and it works yet ...

private static final String TAG = "CountDownTimerSucksActivity";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    new MyCountDownTimer(10000 + iDontWantThis , 1000).start();
}

class MyCountDownTimer extends CountDownTimer {

    long startSec;

    public MyCountDownTimer(long millisInFuture, long countDownInterval) {
        super(millisInFuture, countDownInterval);
        // TODO Auto-generated constructor stub
        startSec = System.currentTimeMillis() ;
    }

    @Override
    public void onFinish() {
        // TODO Auto-generated method stub
        Log.e(TAG, " onFinish (" + getSeconds() + ")");
    }

    @Override
    public void onTick(long millisUntilFinished) {
        // TODO Auto-generated method stub
        Log.e(TAG, millisUntilFinished + " millisUntilFinished" + " (" + getSeconds() + ")");

    }

    protected long getSeconds() {
        return  (((System.currentTimeMillis() - startSec) / 1000) % 60);

    }

}

}

Logcat exiting test run ...

logcat ouput

As you can see, the last onTick call comes from 1963ms millisUntilFinished, then the next onFinished call after almost 2 seconds. Probably a buggy. I found a lot of posts about this, as yet there is no clean solution. I included one in the source code, if you set the iDontWantThis field to 100, it works.

I do not understand workarounds in small fields, but this seems to be such basic functionality that I cannot understand that it has not yet been fixed. What do you do to have a clean solution for this?

UPDATE:

CountDownTimer Sam, - ms, ms

+5
4

, , CountdownTimer; .

handleMessage(), , onTick() .

, , CountdownTimer - Handler, Android. ( 150 ) , .

+8

, , . , . . - , , 500. , , , getSeconds() .

CountdownTimer , , , , StackOverflow " of CountdownTimer?"

+2

, , , API :

" , ".

new CountDownTimer(30000, 1000) {

    public void onTick(long millisUntilFinished) {
        mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
    }

    public void onFinish() {
        mTextField.setText("done!");
    }
}.start();

30 , countDownInterval - 1000, API, 30 . , , .

:

android CountDownTimer -

+1

Android CountDownTimer onTick(), ( ) ( β„– 93)

onTick() , .

If the time remaining until the timer ends is less than the specified time interval, then onTick () is not called ( line number 136 ). For this reason, your last onTick () is not called.

Modified CountDownTimer Class

I changed the timer to call onTick () all the intervals (including the first and last) after the specified delay. This class is -

public abstract class CountDownTimer {

    private final long mMillisInFuture;
    private final long mCountdownInterval;
    private long mStopTimeInFuture;

    private boolean mCancelled = false;

    public CountDownTimer(long millisInFuture, long countDownInterval) {
        mMillisInFuture = millisInFuture;
        mCountdownInterval = countDownInterval;
    }

    public synchronized final void cancel() {
        mCancelled = true;
        mHandler.removeMessages(MSG);
    }

    public synchronized final CountDownTimer start() {
        mCancelled = false;
        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
        onTick(mMillisInFuture);
        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG), mCountdownInterval);
        return this;
    }

    public abstract void onTick(long millisUntilFinished);

    public abstract void onFinish();

    private static final int MSG = 1;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            synchronized (CountDownTimer.this) {
                if (mCancelled)
                    return;
                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
                if (millisLeft <= 0) {
                    onFinish();
                } else {
                    onTick(millisLeft);
                    sendMessageDelayed(obtainMessage(MSG), mCountdownInterval);
                }
            }
        }
    };
}
+1
source

All Articles