¿Temporizador Android? ¿Cómo?

¿Puede alguien dar un ejemplo simple de actualizar un campo de texto cada segundo o algo así?

Quiero hacer una pelota voladora y necesito calcular / actualizar las coordenadas de la pelota cada segundo, por eso necesito algún tipo de temporizador.

No tengo nada de aquí .

Ok ya que esto no está aclarado todavía hay 3 maneras simples de manejar esto. A continuación se muestra un ejemplo de todos los 3 y en la parte inferior es un ejemplo que muestra sólo el método que creo que es preferible. También recuerde limpiar sus tareas en onPause, ahorrando estado si es necesario.

import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Handler.Callback; import android.view.View; import android.widget.Button; import android.widget.TextView; public class main extends Activity { TextView text, text2, text3; long starttime = 0; //this posts a message to the main thread from our timertask //and updates the textfield final Handler h = new Handler(new Callback() { @Override public boolean handleMessage(Message msg) { long millis = System.currentTimeMillis() - starttime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; text.setText(String.format("%d:%02d", minutes, seconds)); return false; } }); //runs without timer be reposting self Handler h2 = new Handler(); Runnable run = new Runnable() { @Override public void run() { long millis = System.currentTimeMillis() - starttime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; text3.setText(String.format("%d:%02d", minutes, seconds)); h2.postDelayed(this, 500); } }; //tells handler to send a message class firstTask extends TimerTask { @Override public void run() { h.sendEmptyMessage(0); } }; //tells activity to run on ui thread class secondTask extends TimerTask { @Override public void run() { main.this.runOnUiThread(new Runnable() { @Override public void run() { long millis = System.currentTimeMillis() - starttime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; text2.setText(String.format("%d:%02d", minutes, seconds)); } }); } }; Timer timer = new Timer(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); text = (TextView)findViewById(R.id.text); text2 = (TextView)findViewById(R.id.text2); text3 = (TextView)findViewById(R.id.text3); Button b = (Button)findViewById(R.id.button); b.setText("start"); b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Button b = (Button)v; if(b.getText().equals("stop")){ timer.cancel(); timer.purge(); h2.removeCallbacks(run); b.setText("start"); }else{ starttime = System.currentTimeMillis(); timer = new Timer(); timer.schedule(new firstTask(), 0,500); timer.schedule(new secondTask(), 0,500); h2.postDelayed(run, 0); b.setText("stop"); } } }); } @Override public void onPause() { super.onPause(); timer.cancel(); timer.purge(); h2.removeCallbacks(run); Button b = (Button)findViewById(R.id.button); b.setText("start"); } } 

La cosa principal a recordar es que la interfaz de usuario sólo se puede modificar desde el hilo principal de ui para utilizar un controlador o activity.runOnUIThread (Runnable r);

Esto es lo que considero el método preferido.

import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.widget.Button; import android.widget.TextView; public class TestActivity extends Activity { TextView timerTextView; long startTime = 0; //runs without a timer by reposting this handler at the end of the runnable Handler timerHandler = new Handler(); Runnable timerRunnable = new Runnable() { @Override public void run() { long millis = System.currentTimeMillis() - startTime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; timerTextView.setText(String.format("%d:%02d", minutes, seconds)); timerHandler.postDelayed(this, 500); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_activity); timerTextView = (TextView) findViewById(R.id.timerTextView); Button b = (Button) findViewById(R.id.button); b.setText("start"); b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Button b = (Button) v; if (b.getText().equals("stop")) { timerHandler.removeCallbacks(timerRunnable); b.setText("start"); } else { startTime = System.currentTimeMillis(); timerHandler.postDelayed(timerRunnable, 0); b.setText("stop"); } } }); } @Override public void onPause() { super.onPause(); timerHandler.removeCallbacks(timerRunnable); Button b = (Button)findViewById(R.id.button); b.setText("start"); } }
import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.widget.Button; import android.widget.TextView; public class TestActivity extends Activity { TextView timerTextView; long startTime = 0; //runs without a timer by reposting this handler at the end of the runnable Handler timerHandler = new Handler(); Runnable timerRunnable = new Runnable() { @Override public void run() { long millis = System.currentTimeMillis() - startTime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; timerTextView.setText(String.format("%d:%02d", minutes, seconds)); timerHandler.postDelayed(this, 500); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_activity); timerTextView = (TextView) findViewById(R.id.timerTextView); Button b = (Button) findViewById(R.id.button); b.setText("start"); b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Button b = (Button) v; if (b.getText().equals("stop")) { timerHandler.removeCallbacks(timerRunnable); b.setText("start"); } else { startTime = System.currentTimeMillis(); timerHandler.postDelayed(timerRunnable, 0); b.setText("stop"); } } }); } @Override public void onPause() { super.onPause(); timerHandler.removeCallbacks(timerRunnable); Button b = (Button)findViewById(R.id.button); b.setText("start"); } } 

¡Es simple! Crea un nuevo temporizador.

 Timer timer = new Timer(); 

A continuación, ampliar la tarea del temporizador

 class UpdateBallTask extends TimerTask { Ball myBall; public void run() { //calculate the new position of myBall } } 

A continuación, agregue la nueva tarea al temporizador con un intervalo de actualización

 final int FPS = 40; TimerTask updateBall = new UpdateBallTask(); timer.scheduleAtFixedRate(updateBall, 0, 1000/FPS); 

Exención de responsabilidad: Esta no es la solución ideal. Esta es la solución usando la clase Timer (como lo pidió OP). En SDK de Android, se recomienda utilizar la clase Handler (hay un ejemplo en la respuesta aceptada).

Si también necesita ejecutar su código en el hilo de la interfaz de usuario (y no en el subproceso del temporizador), eche un vistazo en el blog: http://steve.odyfamily.com/?p=12

 public class myActivity extends Activity { private Timer myTimer; /** Called when the activity is first created. */ @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); myTimer = new Timer(); myTimer.schedule(new TimerTask() { @Override public void run() { TimerMethod(); } }, 0, 1000); } private void TimerMethod() { //This method is called directly by the timer //and runs in the same thread as the timer. //We call the method that will work with the UI //through the runOnUiThread method. this.runOnUiThread(Timer_Tick); } private Runnable Timer_Tick = new Runnable() { public void run() { //This method runs in the same thread as the UI. //Do something to the UI thread here } }; } 

Si sólo desea programar una cuenta atrás hasta un momento en el futuro con notificaciones regulares en intervalos a lo largo del camino, puede utilizar la clase CountDownTimer que está disponible desde el nivel 1 de la API.

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

Este es un código simple para un temporizador:

 final int sekundi = 0 ; Timer timer = new Timer(); TimerTask t = new TimerTask() { int sec = 0; @Override public void run() { System.out.println("1"); } }; timer.scheduleAtFixedRate(t,1000,1000); 

Creo que puedes hacerlo de la manera Rx como:

  timerSubscribe = Observable.interval(1, TimeUnit.SECONDS) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<Long>() { @Override public void call(Long aLong) { //TODO do your stuff } }); 

Y cancelar esto como:

 timerSubscribe.unsubscribe(); 

Rx Timer http://reactivex.io/documentation/operators/timer.html

Desea que sus actualizaciones de interfaz de usuario sucedan en el hilo de interfaz de usuario existente.

La mejor manera es usar un Handler que use postDelayed para ejecutar un Runnable después de un retraso (cada ejecución programa el siguiente); Borre la devolución de llamada con removeCallbacks.

Ya estás buscando en el lugar correcto, así que mira de nuevo, quizás aclare por qué ese código muestra no es lo que quieres. (Véase también el artículo idéntico en Actualización de la interfaz de usuario desde un temporizador ).

He're es la solución más simple, funciona bien en mi aplicación.

  public class MyActivity extends Acitivity { TextView myTextView; boolean someCondition=true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_activity); myTextView = (TextView) findViewById(R.id.refreshing_field); //starting our task which update textview every 1000 ms new RefreshTask().execute(); } //class which updates our textview every second class RefreshTask extends AsyncTask { @Override protected void onProgressUpdate(Object... values) { super.onProgressUpdate(values); String text = String.valueOf(System.currentTimeMillis()); myTextView.setText(text); } @Override protected Object doInBackground(Object... params) { while(someCondition) { try { //sleep for 1s in background... Thread.sleep(1000); //and update textview in ui thread publishProgress(); } catch (InterruptedException e) { e.printStackTrace(); }; return null; } } } 

Debido a que esta pregunta sigue siendo atraer a un montón de usuarios de la búsqueda de google (sobre el temporizador de Android) Me gustaría insertar mis dos monedas.

En primer lugar, la clase Timer será obsoleta en Java 9 (lea la respuesta aceptada) .

La forma sugerida oficial es usar ScheduledThreadPoolExecutor que es más efectivo y rico en características que además puede programar comandos para ejecutar después de un retardo determinado o para ejecutar periódicamente. Además, proporciona flexibilidad y capacidades adicionales de ThreadPoolExecutor.

Aquí hay un ejemplo de uso de funcionalidades simples.

  1. Crear servicio de ejecutor:

     final ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(1); 
  2. Sólo tiene que ejecutar runnable:

     final Future<?> future = SCHEDULER.schedule(Runnable task, long delay,TimeUnit unit); 
  3. Ahora puede utilizar el future para cancelar la tarea o comprobar si se hace por ejemplo:

     future.isDone(); 

Espero que lo encuentre útil para crear tareas en Android.

Ejemplo completo:

 ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); Future<?> sampleFutureTimer = scheduler.schedule(new Runnable(), 120, TimeUnit.SECONDS); if (sampleFutureTimer.isDone()){ // Do something which will save world. } 

Debe crear un subproceso para manejar el bucle de actualización y utilizarlo para actualizar la zona de texto. La parte difícil, sin embargo, es que sólo el hilo principal realmente puede modificar el ui para que el hilo de bucle de actualización necesita para señalar el hilo principal para hacer la actualización. Esto se hace usando un Handler.

Vea este enlace: http://developer.android.com/guide/topics/ui/dialogs.html# Haga clic en la sección titulada "Ejemplo ProgressDialog con un segundo hilo". Es un ejemplo de lo que debe hacer exactamente, excepto con un diálogo de progreso en lugar de un campo de texto.

 void method(boolean u,int max) { uu=u; maxi=max; if (uu==true) { CountDownTimer uy = new CountDownTimer(maxi, 1000) { public void onFinish() { text.setText("Finish"); } @Override public void onTick(long l) { String currentTimeString=DateFormat.getTimeInstance().format(new Date()); text.setText(currentTimeString); } }.start(); } else{text.setText("Stop "); } 

Si alguien está interesado, empecé a jugar con la creación de un objeto estándar para ejecutar en un hilo de UI de actividades. Parece que funciona bien. Comentarios bienvenidos. Me encantaría que esté disponible en el diseñador de diseño como un componente para arrastrar a una actividad. No puedo creer que algo como eso ya no existe.

 package com.example.util.timer; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; public class ActivityTimer { private Activity m_Activity; private boolean m_Enabled; private Timer m_Timer; private long m_Delay; private long m_Period; private ActivityTimerListener m_Listener; private ActivityTimer _self; private boolean m_FireOnce; public ActivityTimer() { m_Delay = 0; m_Period = 100; m_Listener = null; m_FireOnce = false; _self = this; } public boolean isEnabled() { return m_Enabled; } public void setEnabled(boolean enabled) { if (m_Enabled == enabled) return; // Disable any existing timer before we enable a new one Disable(); if (enabled) { Enable(); } } private void Enable() { if (m_Enabled) return; m_Enabled = true; m_Timer = new Timer(); if (m_FireOnce) { m_Timer.schedule(new TimerTask() { @Override public void run() { OnTick(); } }, m_Delay); } else { m_Timer.schedule(new TimerTask() { @Override public void run() { OnTick(); } }, m_Delay, m_Period); } } private void Disable() { if (!m_Enabled) return; m_Enabled = false; if (m_Timer == null) return; m_Timer.cancel(); m_Timer.purge(); m_Timer = null; } private void OnTick() { if (m_Activity != null && m_Listener != null) { m_Activity.runOnUiThread(new Runnable() { @Override public void run() { m_Listener.OnTimerTick(m_Activity, _self); } }); } if (m_FireOnce) Disable(); } public long getDelay() { return m_Delay; } public void setDelay(long delay) { m_Delay = delay; } public long getPeriod() { return m_Period; } public void setPeriod(long period) { if (m_Period == period) return; m_Period = period; } public Activity getActivity() { return m_Activity; } public void setActivity(Activity activity) { if (m_Activity == activity) return; m_Activity = activity; } public ActivityTimerListener getActionListener() { return m_Listener; } public void setActionListener(ActivityTimerListener listener) { m_Listener = listener; } public void start() { if (m_Enabled) return; Enable(); } public boolean isFireOnlyOnce() { return m_FireOnce; } public void setFireOnlyOnce(boolean fireOnce) { m_FireOnce = fireOnce; } } 

En la actividad, tengo esta onStart:

 @Override protected void onStart() { super.onStart(); m_Timer = new ActivityTimer(); m_Timer.setFireOnlyOnce(true); m_Timer.setActivity(this); m_Timer.setActionListener(this); m_Timer.setDelay(3000); m_Timer.start(); } 

Aquí está una manera confiable simple …

Ponga el código siguiente en su actividad y el método tick () se llamará cada segundo en el subproceso de interfaz de usuario mientras su actividad se encuentra en el estado "reanudado". Por supuesto, puede cambiar el método tick () para hacer lo que quiera, o para ser llamado más o menos frecuentemente.

 @Override public void onPause() { _handler = null; super.onPause(); } private Handler _handler; @Override public void onResume() { super.onResume(); _handler = new Handler(); Runnable r = new Runnable() { public void run() { if (_handler == _h0) { tick(); _handler.postDelayed(this, 1000); } } private final Handler _h0 = _handler; }; r.run(); } private void tick() { System.out.println("Tick " + System.currentTimeMillis()); } 

Para los interesados, el código "_h0 = _handler" es necesario para evitar que dos temporizadores se ejecuten simultáneamente si su actividad se detiene y se reanuda dentro del período de tick.

 import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Timer; import java.util.TimerTask; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.TextView; import android.app.Activity; public class MainActivity extends Activity { CheckBox optSingleShot; Button btnStart, btnCancel; TextView textCounter; Timer timer; MyTimerTask myTimerTask; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); optSingleShot = (CheckBox)findViewById(R.id.singleshot); btnStart = (Button)findViewById(R.id.start); btnCancel = (Button)findViewById(R.id.cancel); textCounter = (TextView)findViewById(R.id.counter); btnStart.setOnClickListener(new OnClickListener(){ @Override public void onClick(View arg0) { if(timer != null){ timer.cancel(); } //re-schedule timer here //otherwise, IllegalStateException of //"TimerTask is scheduled already" //will be thrown timer = new Timer(); myTimerTask = new MyTimerTask(); if(optSingleShot.isChecked()){ //singleshot delay 1000 ms timer.schedule(myTimerTask, 1000); }else{ //delay 1000ms, repeat in 5000ms timer.schedule(myTimerTask, 1000, 5000); } }}); btnCancel.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { if (timer!=null){ timer.cancel(); timer = null; } } }); } class MyTimerTask extends TimerTask { @Override public void run() { Calendar calendar = Calendar.getInstance(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a"); final String strDate = simpleDateFormat.format(calendar.getTime()); runOnUiThread(new Runnable(){ @Override public void run() { textCounter.setText(strDate); }}); } } } 

.xml

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context=".MainActivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:autoLink="web" android:text="http://android-er.blogspot.com/" android:textStyle="bold" /> <CheckBox android:id="@+id/singleshot" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Single Shot"/> 

También puede utilizar un animador para ello:

 int secondsToRun = 999; ValueAnimator timer = ValueAnimator.ofInt(secondsToRun); timer.setDuration(secondsToRun * 1000).setInterpolator(new LinearInterpolator()); timer.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int elapsedSeconds = (int) animation.getAnimatedValue(); int minutes = elapsedSeconds / 60; int seconds = elapsedSeconds % 60; textView.setText(String.format("%d:%02d", minutes, seconds)); } }); timer.start(); 

Para aquellos que no pueden confiar en el cronómetro , hice una clase de utilidad de una de las sugerencias:

 public class TimerTextHelper implements Runnable { private final Handler handler = new Handler(); private final TextView textView; private volatile long startTime; private volatile long elapsedTime; public TimerTextHelper(TextView textView) { this.textView = textView; } @Override public void run() { long millis = System.currentTimeMillis() - startTime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; textView.setText(String.format("%d:%02d", minutes, seconds)); if (elapsedTime == -1) { handler.postDelayed(this, 500); } } public void start() { this.startTime = System.currentTimeMillis(); this.elapsedTime = -1; handler.post(this); } public void stop() { this.elapsedTime = System.currentTimeMillis() - startTime; handler.removeCallbacks(this); } public long getElapsedTime() { return elapsedTime; } 

}

Para usar .. solo hacer:

  TimerTextHelper timerTextHelper = new TimerTextHelper(textView); timerTextHelper.start(); 

…..

  timerTextHelper.stop(); long elapsedTime = timerTextHelper.getElapsedTime(); 

Si ya tiene tiempo delta.

 public class Timer { private float lastFrameChanged; private float frameDuration; private Runnable r; public Timer(float frameDuration, Runnable r) { this.frameDuration = frameDuration; this.lastFrameChanged = 0; this.r = r; } public void update(float dt) { lastFrameChanged += dt; if (lastFrameChanged > frameDuration) { lastFrameChanged = 0; r.run(); } } } 
  • Android / phonegap - Tiempo de respuesta del clic lento
  • Crear un temporizador de incremento en segundos en formato 00:00?
  • Timer y TimerTask en Android
  • Cambiar horario scheduleAtFixedRate
  • Pausa CountDownTimer en Android cuando la actividad no está en frente
  • Equivalente a javax.swing.Timer en Android
  • Android: ¿Cómo puedo mostrar un reloj de actualización en un TextView
  • Hacer un temporizador de intervalo en Java android
  • ¿Cómo puedo implementar un Timer / TimerTask que ejecuta un AsyncTask? (Androide)
  • Android: cómo utilizar un temporizador
  • ¿Cómo iniciar una actividad después de cierto período de tiempo?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.