Android CountDownTimer – last onTick no llamado – ¿qué solución limpia para usar?

Puesto de frustración

Acabo de tropezar con el problema "CountDownTimer – last onTick not called" que muchos han reportado aquí.

Demostración simple que muestra el problema

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); } } } 

La salida logcat de una prueba …

Logcat

Como se puede ver la última llamada onTick está ocurriendo con 1963ms millisUntilFinished, entonces la próxima llamada es onFinished casi 2 segundos más tarde. Seguramente un comportamiento de buggy. He encontrado muchos mensajes sobre esto pero no una solución limpia todavía. Uno que incluyo en el código fuente, si se establece el campo iDontWantThis a 100 funciona.

No me importa soluciones en campos menores, sin embargo, esto parece una funcionalidad de núcleo que no puedo entender que no estaba arreglado todavía. ¿Qué está haciendo la gente para tener una solución limpia para esto?

Muchas gracias

martín

ACTUALIZAR:

Una modificación muy útil del CountDownTimer por Sam que no suprime la última garrapata debido al retardo ms interno y también evita la acumulación de retardo ms con cada tic en el tiempo se puede encontrar aquí

3 Solutions collect form web for “Android CountDownTimer – last onTick no llamado – ¿qué solución limpia para usar?”

El comportamiento que está experimentando se define explícitamente en el código CountdownTimer ; Echar un vistazo a la fuente .

Observe dentro de handleMessage() , si el tiempo restante es menor que el intervalo, explícitamente no llama a onTick() y solo retrasa hasta completarse.

Tenga en cuenta, sin embargo, de la fuente que CountdownTimer es sólo un envoltorio muy fino en Handler , que es el componente de tiempo real del marco de Android. Como solución, puede crear fácilmente su propio temporizador de esta fuente (menos de 150 líneas) y eliminar esta restricción para obtener la devolución de llamada final de la marca.

Creo que la frustración proviene de una expectativa incorrecta de lo que debería ser una garrapata. Como la otra respuesta señaló, este comportamiento es intencional. Otra manera posible de manejar esto es simplemente especificar un intervalo más pequeño. Si estaba implementando algún tipo de reloj de cuenta regresiva por ejemplo, no le haría daño cambiar el intervalo a 500. Si es importante que algún trabajo solo se haga cuando los segundos cambian, también puede hacerlo almacenando el resultado de getSeconds() Y sólo hacer ese trabajo cuando cambia ese valor.

Si CountdownTimer se cambió para disparar siempre que la última marca, incluso si el tiempo restante es menor que el intervalo, estoy seguro de StackOverflow tendría un montón de preguntas como "¿por qué no tengo tiempo suficiente en la última garrapata de CountdownTimer ?

No entiendo por qué usted dice que es un comportamiento intencional, el API dice exactamente:

"Programar una cuenta atrás hasta un momento en el futuro, con notificaciones regulares en intervalos a lo largo del camino."

 new CountDownTimer(30000, 1000) { public void onTick(long millisUntilFinished) { mTextField.setText("seconds remaining: " + millisUntilFinished / 1000); } public void onFinish() { mTextField.setText("done!"); } }.start(); 

Si establece el tiempo en 30 segundos y el countDownInterval en 1000, como dice la API regular, debe dispararse exactamente 30 veces. Creo que no es un comportamiento intencional sino una implementación incorrecta.

La solución debería ser la propuesta por Sam aquí:

Android CountDownTimer – retraso de milisegundos adicional entre las garrapatas

  • Temporizador Android actualizando una vista de texto (UI)
  • Android: desea que la aplicación realice tareas cada segundo
  • ¿Cómo puedo cancelar desde Device.StartTimer?
  • Enviar notificación una vez por semana
  • Pausa CountDownTimer en Android cuando la actividad no está en frente
  • Android: contador simple del tiempo
  • Lanzar null pointerException en Timer.Schedule ();
  • Android ViewPager cambia automáticamente la página
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.