¿Cómo pausar/suspendir hilo o proceso en Android?
Quiero hacer una pausa entre dos líneas de código. Déjame explicarte un poco:
-> el usuario hace clic en un botón (una tarjeta de hecho) y lo muestro cambiando el fondo de este botón:
thisbutton.setBackgroundResource(R.drawable.icon);
-> después de, digamos, 1 segundo, necesito volver al estado anterior del botón cambiando su fondo:
thisbutton.setBackgroundResource(R.drawable.defaultcard);
-> Intenté pausar el hilo entre estas dos líneas de código con:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Sin embargo, esto no funciona. ¿Quizás sea el proceso y no el hilo lo que necesito pausar?
También lo intenté (pero no funciona):
new Reminder(5);
Con este:
public class Reminder {
Timer timer;
public Reminder(int seconds) {
timer = new Timer();
timer.schedule(new RemindTask(), seconds*1000);
}
class RemindTask extends TimerTask {
public void run() {
System.out.format("Time's up!%n");
timer.cancel(); //Terminate the timer thread
}
}
}
¿Cómo puedo pausar/dormir el hilo o proceso?
Una solución a este problema es utilizar el método Handler.postDelayed() . Algunos materiales de formación de Google sugieren la misma solución.
@Override
public void onClick(View v) {
my_button.setBackgroundResource(R.drawable.icon);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
my_button.setBackgroundResource(R.drawable.defaultcard);
}
}, 2000);
}
Sin embargo, algunos han señalado que la solución anterior provoca una pérdida de memoria porque utiliza una clase interna y anónima no estática que implícitamente contiene una referencia a su clase externa, la actividad. Esto es un problema cuando el contexto de la actividad es recolección de basura.
Una solución más compleja que evita la pérdida de memoria subclases Handler
y Runnable
con clases internas estáticas dentro de la actividad, ya que las clases internas estáticas no contienen una referencia implícita a su clase externa:
private static class MyHandler extends Handler {}
private final MyHandler mHandler = new MyHandler();
public static class MyRunnable implements Runnable {
private final WeakReference<Activity> mActivity;
public MyRunnable(Activity activity) {
mActivity = new WeakReference<>(activity);
}
@Override
public void run() {
Activity activity = mActivity.get();
if (activity != null) {
Button btn = (Button) activity.findViewById(R.id.button);
btn.setBackgroundResource(R.drawable.defaultcard);
}
}
}
private MyRunnable mRunnable = new MyRunnable(this);
public void onClick(View view) {
my_button.setBackgroundResource(R.drawable.icon);
// Execute the Runnable in 2 seconds
mHandler.postDelayed(mRunnable, 2000);
}
Tenga en cuenta que Runnable
utiliza una referencia débil a la actividad, que es necesaria en una clase estática que necesita acceso a la interfaz de usuario.
Puedes probar este, es corto.
SystemClock.sleep(7000);
ADVERTENCIA : Nunca, nunca, hagas esto en un hilo de la interfaz de usuario.
Utilice esto para dormir, por ejemplo. hilo de fondo.
La solución completa para su problema será: Esta está disponible API 1
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View button) {
button.setBackgroundResource(R.drawable.avatar_dead);
final long changeTime = 1000L;
button.postDelayed(new Runnable() {
@Override
public void run() {
button.setBackgroundResource(R.drawable.avatar_small);
}
}, changeTime);
}
});
Sin crear tmp Handler. Además, esta solución es mejor que @tronman porque no conservamos la vista del controlador. Además, no tenemos problemas con el controlador creado en un hilo incorrecto;)
Documentación
sueño vacío estático público (ms largos)
Agregado en API nivel 1
Espera una cantidad determinada de milisegundos (de uptimeMillis) antes de regresar. Similar a dormir (largo), pero no arroja InterruptedException ; Los eventos de interrupción() se difieren hasta la siguiente operación interrumpible. No regresa hasta que haya transcurrido al menos el número especificado de milisegundos.
Parámetros
ms para dormir antes de regresar, en milisegundos de tiempo de actividad.
Código para postDelayed de la clase Ver:
/**
* <p>Causes the Runnable to be added to the message queue, to be run
* after the specified amount of time elapses.
* The runnable will be run on the user interface thread.</p>
*
* @param action The Runnable that will be executed.
* @param delayMillis The delay (in milliseconds) until the Runnable
* will be executed.
*
* @return true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the Runnable will be processed --
* if the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*
* @see #post
* @see #removeCallbacks
*/
public boolean postDelayed(Runnable action, long delayMillis) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.postDelayed(action, delayMillis);
}
// Assume that post will succeed later
ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
return true;
}
Yo uso esto:
Thread closeActivity = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
// Do some stuff
} catch (Exception e) {
e.getLocalizedMessage();
}
}
});