2012-09-14 9 views
5

frustración publicación ....android CountDownTimer - last onTick no llamado - ¿qué solución limpia usar?

Acabo de tropezar con el problema "CountDownTimer - el último en el truco no llamado" que muchos han informado 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 de funcionamiento ...

logcat ouput

Como se puede ver la última llamada onTick está sucediendo con 1963ms millisUntilFinished, a continuación, la próxima llamada se iniciará casi 2 segundos después. Sin duda, un comportamiento con errores. Encontré muchas publicaciones sobre esta aún ninguna solución limpia todavía. Uno que incluí en el código fuente, si configura el campo iDontWantThis en 100, funciona.

No me preocupo por las soluciones en campos menores, sin embargo, esto parece ser una funcionalidad básica que no puedo entender que todavía no se haya solucionado. ¿Qué están haciendo las personas para tener una solución limpia para esto?

Muchas gracias

martin

ACTUALIZACIÓN:

Una modificación muy útil de la countDownTimer por Sam que no surpresses la última señal debido a un retraso ms interna y también evita la acumulación de ms retraso con cada tic en el tiempo se puede encontrar here

Respuesta

8

El comportamiento que está experimentando se define explícitamente en la actualidad CountdownTimer código; have a look at the source.

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

Sin embargo, tenga en cuenta que CountdownTimer es simplemente una envoltura muy delgada en Handler, que es el componente de tiempo real del marco de Android. Como solución alternativa, puede crear fácilmente su propio temporizador desde esta fuente (menos de 150 líneas) y eliminar esta restricción para obtener su devolución de llamada final.

+0

Muchas gracias, bastante nuevo en Android y que no he hecho el paso para mirar realmente en su código fuente en los casos por el estilo. Muchas gracias por señalarme ese paso. Implementaré mi propio CountDownTimer como se sugiere, que siempre llama a Tick si millisUntilFinished> 0 y puedo verificar fácilmente si el milímetro restante permite lo que quiero hacer (en realidad solo necesito el temporizador de cuenta regresiva que muestra 6,5,4,3,2 , 1,0) – dorjeduck

+0

solo para completar, eliminando lo siguiente si el bloque realiza el trabajo para que se llame aTick cuando haya millones restantes ------------------- ---------------------------------------------} else if (millisLeft) dorjeduck

2

Creo que la frustración proviene de una expectativa incorrecta de lo que debe ser un tic. Como se observó en la otra respuesta, este comportamiento es intencional. Otra forma posible de manejar esto es simplemente especificar un intervalo más pequeño. Si estuviera implementando algún tipo de reloj de cuenta regresiva por ejemplo, no estaría de más cambiar el intervalo a 500. Si es importante que algo de trabajo solo se realice cuando los segundos cambian, puede hacerlo almacenando el resultado de getSeconds() y solo haciendo ese trabajo cuando ese valor cambie.

Si CountdownTimer se cambiaron para activar siempre el último tick, incluso si el tiempo restante es inferior al intervalo, estoy seguro de que StackOverflow tendría un montón de preguntas como "¿por qué no tengo suficiente tiempo en el último tic de CountdownTimer?"

+0

Tiene razón, solo esperaba un comportamiento diferente, que es la fuente de la frustración. Me sorprende que el comportamiento previsto no se mencione en el documento de la API, especialmente porque en el logcat anterior se puede ver que el temporizador de cuenta regresiva es "tarde" con cada tic cuando se dispara 47 ms más tarde que los segundos indicados Left/intervals y eso mismo 47ms hace que onTick no se llame como lo esperaba. Solo imagina el caso en el que das 4 horas como intervalo, que esperaría que no se llame a Tick por 43ms. Pero sí, ese es el problema con las expectativas;) – dorjeduck

1

No entiendo por qué dices que es un comportamiento intencional, la API dice exactamente:

'programar una cuenta atrás hasta un momento en el futuro, con las 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 se establece el tiempo de 30 segundos, y el countDownInterval a 1000, ya que la API dice regular, debe ser despedido exactamente 30 veces. Creo que no es un comportamiento intencional, sino una aplicación equivocada.

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

android CountDownTimer - additional milliseconds delay between ticks

+0

Gracias Juan - La solución de Sam ya se menciona en la actualización de la publicación. – dorjeduck

Cuestiones relacionadas