Je veux faire une pause entre deux lignes de code, laissez-moi vous expliquer un peu:
-> l'utilisateur clique sur un bouton (une carte en fait) et je le montre en changeant le fond de ce bouton:
thisbutton.setBackgroundResource(R.drawable.icon);
-> après 1 seconde, je dois revenir à l'état précédent du bouton en modifiant l'arrière-plan:
thisbutton.setBackgroundResource(R.drawable.defaultcard);
-> J'ai essayé de mettre en pause le fil entre ces deux lignes de code avec:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Cependant, cela ne fonctionne pas. Peut-être que c'est le processus et non le fil que je dois faire une pause?
J'ai aussi essayé (mais ça ne marche pas):
new Reminder(5);
Avec ça:
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
}
}
}
Comment puis-je suspendre/dormir le fil ou le processus?
Une solution à ce problème consiste à utiliser la méthode Handler.postDelayed () . Certains supports Google training suggèrent la même solution.
@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);
}
Cependant, certains ont fait remarquer que la solution ci-dessus provoquait une fuite de mémoire , car elle utilisait une classe interne et anonyme non statique qui contient implicitement une référence à sa classe externe, l'activité. C'est un problème lorsque le contexte de l'activité est collecté.
Une solution plus complexe qui évite les fuites de mémoire. Les sous-classes Handler
et Runnable
avec des classes internes statiques au sein de l'activité, car les classes internes statiques ne contiennent pas de référence implicite à leur classe externe:
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);
}
Notez que la Runnable
utilise un WeakReference pour l'activité, ce qui est nécessaire dans une classe statique nécessitant un accès à l'interface utilisateur.
Vous pouvez essayer celui-ci il est short
SystemClock.sleep(7000);
WARNING: Ne faites jamais cela sur un thread d'interface utilisateur.
Utilisez ceci pour dormir par exemple. fil de fond.
La solution complète à votre problème sera: Ceci 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);
}
});
Sans créer tmp Handler. De plus, cette solution est meilleure que @tronman car nous ne conservons pas la vue par Handler . Nous n’avons pas non plus de problème avec Handler créé à un mauvais thread;)
public vide statique sommeil (long ms)
Ajouté dans l'API niveau 1
Attend un nombre donné de millisecondes (de disponibilité), avant de revenir. Similaire à sleep (long), mais ne lève pas InterruptedException; Les événements interrupt () sont différés jusqu'au prochaine opération interruptible. Ne renvoie-t-il pas jusqu'à ce que le nombre de millisecondes spécifié se soit au moins écoulé?.
Paramètres
ms pour dormir avant de revenir, en millisecondes de disponibilité.
Code pour postDelayed from Afficher la classe:
/**
* <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;
}
J'utilise ceci:
Thread closeActivity = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
// Do some stuff
} catch (Exception e) {
e.getLocalizedMessage();
}
}
});
Vous ne voulez probablement pas le faire de cette façon. En plaçant une sleep()
explicite dans votre gestionnaire d'événements sur lequel vous avez cliqué, vous verrouillez l'interface utilisateur entière pendant une seconde. Une alternative consiste à utiliser une sorte de simple coup Minuterie . Créez une TimerTask pour changer la couleur d'arrière-plan à la couleur par défaut et programmez-la sur le minuteur.
Une autre possibilité consiste à utiliser un Handler . Il y a un tutoriel à propos de quelqu'un qui a abandonné l'utilisation d'un minuteur pour utiliser un gestionnaire.
Incidemment, vous ne pouvez pas suspendre un processus. Un processus Java (ou Android) comporte au moins 1 thread et vous ne pouvez mettre en veille que les threads.
J'utilise 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();
C’est ce que j’ai fait à la fin de la journée - cela fonctionne bien maintenant:
@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);
}
En plus des réponses de M. Yankowsky, vous pouvez également utiliser postDelayed()
. Ceci est disponible sur n’importe quel View
(par exemple, votre carte) et prend un Runnable
et une période de retard. Il exécute Runnable
après ce délai.
Ceci est mon exemple
Créer un utilitaire Java
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();
}
}
Ou vous pouvez utiliser:
Android.os.SystemClock.sleep(checkEvery)
ce qui a l'avantage de ne pas nécessiter de wrapping try ... catch
.
Je sais que c'est un vieux fil, mais dans la documentation Android, j'ai trouvé une solution qui fonctionnait très bien pour moi ...
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
https://developer.Android.com/reference/Android/os/CountDownTimer.html
J'espère que ça aide quelqu'un ...
Si vous utilisez Kotlin et coroutines , vous pouvez simplement faire
GlobalScope.launch {
delay(3000) // In ms
//Code after sleep
}
Et si vous avez besoin de mettre à jour l'interface utilisateur
GlobalScope.launch {
delay(3000)
GlobalScope.launch(Dispatchers.Main) {
//Action on UI thread
}
}