tiempo - ¿Cómo pausar/dormir hilo o procesar en Android?
thread android studio (9)
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 decir 1 segundo, tengo que volver al estado anterior del botón cambiando de nuevo su fondo:
thisbutton.setBackgroundResource(R.drawable.defaultcard);
-> He intentado 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. Tal vez es el proceso y no el hilo que necesito hacer una pausa?
También he intentado (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 el proceso?
Además de las respuestas del Sr. Yankowsky, también puede usar postDelayed()
. Esto está disponible en cualquier View
(por ejemplo, su tarjeta) y toma un Runnable
y un período de demora. Ejecuta el Runnable
después de ese retraso.
Este es mi ejemplo
Crear un Java Utils
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
public class Utils {
public static void showDummyWaitingDialog(final Context context, final Intent startingIntent) {
// ...
final ProgressDialog progressDialog = ProgressDialog.show(context, "Please wait...", "Loading data ...", true);
new Thread() {
public void run() {
try{
// Do some work here
sleep(5000);
} catch (Exception e) {
}
// start next intent
new Thread() {
public void run() {
// Dismiss the Dialog
progressDialog.dismiss();
// start selected activity
if ( startingIntent != null) context.startActivity(startingIntent);
}
}.start();
}
}.start();
}
}
Esto es lo que hice al final del día, funciona bien ahora:
@Override
public void onClick(View v) {
my_button.setBackgroundResource(R.drawable.icon);
// SLEEP 2 SECONDS HERE ...
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
my_button.setBackgroundResource(R.drawable.defaultcard);
}
});
}
}, 2000);
}
O podrías usar:
android.os.SystemClock.sleep(checkEvery)
que tiene la ventaja de no requerir un try ... catch
envoltura try ... catch
.
Probablemente no quieras hacerlo de esa manera. Al poner un sleep()
explícito en el controlador de eventos con un clic de botón, en realidad bloquearía toda la IU durante un segundo. Una alternativa es usar algún tipo de Timer disparo único. Cree una TimerTask de TimerTask para cambiar el color de fondo al color predeterminado y programarlo en el temporizador.
Otra posibilidad es usar un Handler.postDelayed() . Hay un tutorial sobre alguien que cambió de usar un temporizador a usar un controlador.
Por cierto, no puedes pausar un proceso. Un proceso Java (o Android) tiene al menos 1 subproceso, y solo puedes dormir subprocesos.
Puedes probar este es corto.
SystemClock.sleep(7000);
ADVERTENCIA : Nunca, nunca, haga esto en un hilo de UI.
Usa esto para dormir, por ejemplo. hilo de fondo
La solución completa para su problema será: Esta API está disponible 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 el controlador tmp. Además, esta solución es mejor que @tronman porque no conservamos la vista de Handler. Tampoco tenemos problemas con Handler creado en el hilo mal;)
Sueño vacío público estático (ms largo)
Añadido en el nivel API 1
Espera un número dado de milisegundos (de uptimeMillis) antes de regresar. Similar a dormir (largo), pero no lanza InterruptedException ; Los eventos de interrupción () se aplazan hasta la siguiente operación interrumpible. No vuelve hasta que haya transcurrido al menos el número especificado de milisegundos.
Parámetros
Para dormir antes de volver, en milisegundos de tiempo de actividad.
Código para postDelayed from View class:
/**
* <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;
}
Una solución a este problema es usar el método Handler.postDelayed() . Algunos materiales de capacitació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 causa 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. Este es un problema cuando el contexto de la actividad se recolecta como basura.
Una solución más compleja que evita las subclases de pérdida de memoria, el Runnable
y Runnable
con clases internas estáticas dentro de la actividad, ya que las clases internas estáticas no tienen 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 WeakReference a la actividad, que es necesaria en una clase estática que necesita acceso a la UI.
Yo uso CountDownTime
new CountDownTimer(5000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
// do something after 1s
}
@Override
public void onFinish() {
// do something end times 5s
}
}.start();
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();
}
}
});