¿Repite una tarea con un retardo de tiempo?

Tengo una variable en mi código decir que es "estado".

Quiero mostrar algún texto en la aplicación dependiendo de este valor de la variable. Esto tiene que hacerse con un retardo de tiempo específico.

Es como,

  • Comprobar el valor de la variable de estado

  • Mostrar texto

  • Espere 10 segundos

  • Comprobar el valor de la variable de estado

  • Mostrar texto

  • Espere 15 segundos

y así. El retardo puede variar y se ajusta una vez que se muestra el texto.

He intentado Thread.sleep(time delay) y ha fallado. ¿Hay alguna manera mejor de hacer esto?

Debe utilizar la función postDelayed Handler para este propósito. Se ejecutará el código con el retraso especificado en el hilo principal de la interfaz de usuario, por lo que será capaz de actualizar los controles de interfaz de usuario.

 private int mInterval = 5000; // 5 seconds by default, can be changed later private Handler mHandler; @Override protected void onCreate(Bundle bundle) { // your code here mHandler = new Handler(); startRepeatingTask(); } @Override public void onDestroy() { super.onDestroy(); stopRepeatingTask(); } Runnable mStatusChecker = new Runnable() { @Override public void run() { try { updateStatus(); //this function can change value of mInterval. } finally { // 100% guarantee that this always happens, even if // your update method throws an exception mHandler.postDelayed(mStatusChecker, mInterval); } } }; void startRepeatingTask() { mStatusChecker.run(); } void stopRepeatingTask() { mHandler.removeCallbacks(mStatusChecker); } 

Para cualquier persona interesada, aquí está una clase que creé usando el código de inazaruk que crea todo lo necesario (lo llamé UIUpdater porque lo uso para actualizar periódicamente la interfaz de usuario, pero puedes llamarla como quieras):

 import android.os.Handler; /** * A class used to perform periodical updates, * specified inside a runnable object. An update interval * may be specified (otherwise, the class will perform the * update every 2 seconds). * * @author Carlos Simões */ public class UIUpdater { // Create a Handler that uses the Main Looper to run in private Handler mHandler = new Handler(Looper.getMainLooper()); private Runnable mStatusChecker; private int UPDATE_INTERVAL = 2000; /** * Creates an UIUpdater object, that can be used to * perform UIUpdates on a specified time interval. * * @param uiUpdater A runnable containing the update routine. */ public UIUpdater(final Runnable uiUpdater) { mStatusChecker = new Runnable() { @Override public void run() { // Run the passed runnable uiUpdater.run(); // Re-run it after the update interval mHandler.postDelayed(this, UPDATE_INTERVAL); } }; } /** * The same as the default constructor, but specifying the * intended update interval. * * @param uiUpdater A runnable containing the update routine. * @param interval The interval over which the routine * should run (milliseconds). */ public UIUpdater(Runnable uiUpdater, int interval){ UPDATE_INTERVAL = interval; this(uiUpdater); } /** * Starts the periodical update routine (mStatusChecker * adds the callback to the handler). */ public synchronized void startUpdates(){ mStatusChecker.run(); } /** * Stops the periodical update routine from running, * by removing the callback. */ public synchronized void stopUpdates(){ mHandler.removeCallbacks(mStatusChecker); } } 

A continuación, puede crear un objeto UIUpdater dentro de su clase y utilizarlo de la siguiente manera:

 ... mUIUpdater = new UIUpdater(new Runnable() { @Override public void run() { // do stuff ... } }); // Start updates mUIUpdater.startUpdates(); // Stop updates mUIUpdater.stopUpdates(); ... 

Si desea utilizar esto como un actualizador de actividad, coloque la llamada de inicio dentro del método onResume () y la llamada de detención dentro de la onPause (), por lo que las actualizaciones se inician y se detienen según la visibilidad de la actividad.

Creo que el nuevo hotness es usar un ScheduledThreadPoolExecutor . Al igual que:

 private final ScheduledThreadPoolExecutor executor_ = new ScheduledThreadPoolExecutor(1); this.executor_.scheduleWithFixedDelay(new Runnable() { @Override public void run() { update(); } }, 0L, kPeriod, kTimeUnit); 

El temporizador es otra forma de hacer su trabajo, pero asegúrese de agregar runOnUiThread si está trabajando con la interfaz de usuario.

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

Y xml es …

 <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"/> 

Otra manera de usar CountDownTimer

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

Programe una cuenta regresiva hasta un momento en el futuro, con notificaciones regulares sobre los intervalos en el camino. Ejemplo de mostrar una cuenta regresiva de 30 segundos en un campo de texto:

Para detalles

Puede utilizar un controlador para publicar código ejecutables. Esta técnica se describe muy bien aquí: https://guides.codepath.com/android/Repeating-Periodic-Tasks

Prueba el ejemplo siguiente funciona !!!

Utilice [Handler] en el método onCreate () que hace uso del método postDelayed () que hace que Runnable se agregue a la cola de mensajes, que se ejecutará después de que transcurra la cantidad de tiempo especificada que es 0 en un ejemplo dado. 1

Refiérase a este código:


 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //------------------ //------------------ android.os.Handler customHandler = new android.os.Handler(); customHandler.postDelayed(updateTimerThread, 0); } private Runnable updateTimerThread = new Runnable() { public void run() { //write here whaterver you want to repeat customHandler.postDelayed(this, 1000); } }; 

En mi caso, tuve que ejecutar un proceso si una de estas condiciones era verdadera: si un proceso anterior fue completado o si 5 segundos habían pasado ya. Así que hice lo siguiente y trabajé bastante bien:

 private Runnable mStatusChecker; private Handler mHandler; class { method() { mStatusChecker = new Runnable() { int times = 0; @Override public void run() { if (times < 5) { if (process1.isRead()) { executeProcess2(); } else { times++; mHandler.postDelayed(mStatusChecker, 1000); } } else { executeProcess2(); } } }; mHandler = new Handler(); startRepeatingTask(); } void startRepeatingTask() { mStatusChecker.run(); } void stopRepeatingTask() { mHandler.removeCallbacks(mStatusChecker); } } 

Si se lee process1, ejecuta process2. De lo contrario, incrementa los tiempos de la variable y hace que el manejador se ejecute después de un segundo. Mantiene un bucle hasta que se lee el proceso 1 o el tiempo es 5. Cuando los tiempos son 5, significa que pasan 5 segundos y en cada segundo se ejecuta la cláusula if de process1.isRead ().

El temporizador funciona bien. Aquí, yo uso Timer para buscar texto después de 1.5s y actualizar la interfaz de usuario. Espero que ayude.

 private Timer _timer = new Timer(); _timer.schedule(new TimerTask() { @Override public void run() { // use runOnUiThread(Runnable action) runOnUiThread(new Runnable() { @Override public void run() { search(); } }); } }, timeInterval); 

Basándome en el post anterior sobre el ScheduledThreadPoolExecutor , me ocurrió una utilidad que se adaptó a mis necesidades (quería disparar un método cada 3 segundos):

 class MyActivity { private ScheduledThreadPoolExecutor mDialogDaemon; private void initDebugButtons() { Button btnSpawnDialogs = (Button)findViewById(R.id.btn_spawn_dialogs); btnSpawnDialogs.setVisibility(View.VISIBLE); btnSpawnDialogs.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { spawnDialogs(); } }); } private void spawnDialogs() { if (mDialogDaemon != null) { mDialogDaemon.shutdown(); mDialogDaemon = null; } mDialogDaemon = new ScheduledThreadPoolExecutor(1); // This process will execute immediately, then execute every 3 seconds. mDialogDaemon.scheduleAtFixedRate(new Runnable() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { // Do something worthwhile } }); } }, 0L, 3000L, TimeUnit.MILLISECONDS); } } 

Hágalo de forma Android con la ayuda de Handler .

Declare una clase Handler interna que no pierda memoria en su clase de actividad / fragmento

 /** * Instances of static inner classes do not hold an implicit * reference to their outer class. */ private static class NonLeakyHandler extends Handler { private final WeakReference<FlashActivity> mActivity; public NonLeakyHandler(FlashActivity activity) { mActivity = new WeakReference<FlashActivity>(activity); } @Override public void handleMessage(Message msg) { FlashActivity activity = mActivity.get(); if (activity != null) { // ... } } } 

Declare un runnable que realizará su tarea repetitiva en su clase Activity / Fragment

  private Runnable repeatativeTaskRunnable = new Runnable() { public void run() { new Handler(getMainLooper()).post(new Runnable() { @Override public void run() { //DO YOUR THINGS } }; 

Inicializar el objeto Handler en tu Actividad / Fragmento (aquí FlashActivity es mi clase de actividad)

 //Task Handler private Handler taskHandler = new NonLeakyHandler(FlashActivity.this); 

Para repetir una tarea después de un intervalo de tiempo fijo

TaskHandler.postDelayed (repeatativeTaskRunnable, DELAY_MILLIS);

Para detener la repetición de la tarea

TaskHandler .removeCallbacks (repetiatativeTaskRunnable);

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.