Comment définir le retard dans Android?

165
public void onClick(View v) {
        // TODO Auto-generated method stub
        switch(v.getId()){
        case R.id.rollDice:
            Random ranNum = new Random();
            int number = ranNum.nextInt(6) + 1;
            diceNum.setText(""+number);
            sum = sum + number;
            for(i=0;i<8;i++){
                for(j=0;j<8;j++){

                    int value =(Integer)buttons[i][j].getTag();
                    if(value==sum){
                        inew=i;
                        jnew=j;

                        buttons[inew][jnew].setBackgroundColor(Color.BLACK);
                                                //I want to insert a delay here
                        buttons[inew][jnew].setBackgroundColor(Color.WHITE);
                         break;                     
                    }
                }
            }


            break;

        }
    }

Je veux définir un délai entre la commande entre le changement d'arrière-plan. J'ai essayé d'utiliser un minuteur de fil et j'ai essayé d'utiliser run and catch. Mais ça ne marche pas. J'ai essayé ça

 Thread timer = new Thread() {
            public void run(){
                try {
                                buttons[inew][jnew].setBackgroundColor(Color.BLACK);
                    sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

             }
           };
    timer.start();
   buttons[inew][jnew].setBackgroundColor(Color.WHITE);

Mais il ne fait que devenir noir.

Kenneth Joseph Paul
la source

Réponses:

501

Essayez ce code:

import android.os.Handler;
...
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        // Do something after 5s = 5000ms
        buttons[inew][jnew].setBackgroundColor(Color.BLACK);
    }
}, 5000);
Tuan Vu
la source
1
Cette solution a expliqué toutes les questions que j'avais avec les gestionnaires à certaines lignes de code.
Sierisimo
45
Je reviens toujours sur ce post car je suis trop paresseux pour l'écrire à chaque fois. Je vous remercie.
Eugene H
Eh bien, ça va bien mais j'ai beaucoup de message à attendre puis à montrer. donc les bandes de roulement multiples posent problème. comment peut résoudre le problème de plusieurs bandes de roulement
mehmet
2
Cette solution produit une fuite de mémoire car elle utilise une classe interne et anonyme non statique qui contient implicitement une référence à sa classe externe, l'activité. Voir stackoverflow.com/questions/1520887/… pour une meilleure solution.
tronman
@EugeneH Utilisez des modèles en direct pour une vie plus facile stackoverflow.com/a/16870791/4565796
Saeed Arianmanesh
38

Vous pouvez utiliser CountDownTimerce qui est beaucoup plus efficace que toute autre solution publiée. Vous pouvez également produire des notifications régulières à intervalles réguliers en utilisant sa onTick(long)méthode

Jetez un œil à cet exemple montrant un compte à rebours de 30 secondes

   new CountDownTimer(30000, 1000) {
         public void onFinish() {
             // When timer is finished 
             // Execute your code here
     }

     public void onTick(long millisUntilFinished) {
              // millisUntilFinished    The amount of time until finished.
     }
   }.start();
Soufiyan Ghori
la source
23

Si vous utilisez fréquemment le délai dans votre application, utilisez cette classe d'utilitaire

import android.os.Handler;


public class Utils {

    // Delay mechanism

    public interface DelayCallback{
        void afterDelay();
    }

    public static void delay(int secs, final DelayCallback delayCallback){
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                delayCallback.afterDelay();
            }
        }, secs * 1000); // afterDelay will be executed after (secs*1000) milliseconds.
    }
}

Usage:

// Call this method directly from java file

int secs = 2; // Delay in seconds

Utils.delay(secs, new Utils.DelayCallback() {
    @Override
    public void afterDelay() {
        // Do something after delay

    }
});
aruke
la source
1
Pourquoi ? C'est une pure surcharge et complexité ... pour rien
juloo65
Si nous utilisons des retards fréquents, alors avoir un format fixe pour les retards est très bien. Je ne pense pas qu'il y ait beaucoup de frais généraux à cause d'une interface et d'une méthode supplémentaires.
aruke
18

En utilisant la Thread.sleep(millis)méthode.

user2270457
la source
30
ne faites pas cela sur le thread de l'interface utilisateur - d'autres éléments peuvent également cesser de répondre et se comporter plus tard de manière imprévisible
jmaculate
1
merci pour l'avertissement. c'est exactement ce dont j'ai besoin, pour retarder le thread de l'interface utilisateur. réponse parfaite à mes besoins. Merci.
hamish
7

Si vous voulez faire quelque chose dans l'interface utilisateur à des intervalles de temps réguliers, une très bonne option est d'utiliser CountDownTimer:

new CountDownTimer(30000, 1000) {

     public void onTick(long millisUntilFinished) {
         mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
     }

     public void onFinish() {
         mTextField.setText("done!");
     }
  }.start();
Ivo Stoyanov
la source
C'est plus propre que le Handler .
Ahsan
3

Réponse du gestionnaire à Kotlin:

1 - Créez une fonction de niveau supérieur dans un fichier (par exemple un fichier contenant toutes vos fonctions de niveau supérieur):

fun delayFunction(function: ()-> Unit, delay: Long) {
    Handler().postDelayed(function, delay)
}

2 - Ensuite, appelez-le partout où vous en avez besoin:

delayFunction({ myDelayedFunction() }, 300)
Phil
la source
2

Vous pouvez utiliser ceci:

import java.util.Timer;

et pour le retard lui-même, ajoutez:

 new Timer().schedule(
                    new TimerTask(){
                
                        @Override
                        public void run(){
                            
                        //if you need some code to run when the delay expires
                        }
                        
                    }, delay);

où la delayvariable est en millisecondes; par exemple réglé delaysur 5000 pour un délai de 5 secondes.

Dror
la source
0

Voici un exemple où je change l'image d'arrière-plan de l'une à l'autre avec un délai de fondu alpha de 2 secondes dans les deux sens - un fondu de 2s de l'image d'origine en un fondu de 2s dans la 2ème image.

    public void fadeImageFunction(View view) {

    backgroundImage = (ImageView) findViewById(R.id.imageViewBackground);
    backgroundImage.animate().alpha(0f).setDuration(2000);

    // A new thread with a 2-second delay before changing the background image
    new Timer().schedule(
            new TimerTask(){
                @Override
                public void run(){
                    // you cannot touch the UI from another thread. This thread now calls a function on the main thread
                    changeBackgroundImage();
                }
            }, 2000);
   }

// this function runs on the main ui thread
private void changeBackgroundImage(){
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            backgroundImage = (ImageView) findViewById(R.id.imageViewBackground);
            backgroundImage.setImageResource(R.drawable.supes);
            backgroundImage.animate().alpha(1f).setDuration(2000);
        }
    });
}
MuharizJ
la source