Como definir o atraso no android?

164
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;

        }
    }

Quero definir um atraso entre o comando entre alterar o plano de fundo. Tentei usar um cronômetro de threads e tentei correr e capturar. Mas não está funcionando. Eu tentei isso

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

Mas está apenas mudando para preto.

Kenneth Joseph Paul
fonte

Respostas:

499

Tente este código:

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
fonte
1
Esta solução explicou todas as perguntas que tive com manipuladores em algumas linhas de código.
Sierisimo 19/05
45
Eu sempre volto a este post porque tenho preguiça de escrevê-lo todas as vezes. Obrigado.
9306 Eugene H
bem, parece legal, mas tenho muitas mensagens para esperar e mostrar. passos tão multible dar problema. como pode resolver vários degraus problema
mehmet
2
Essa solução produz um vazamento de memória porque usa uma classe interna e anônima não estática que contém implicitamente uma referência à sua classe externa, a atividade. Consulte stackoverflow.com/questions/1520887/… para obter uma solução melhor.
tronman
@EugeneH usar o Live Templates para facilitar a vida stackoverflow.com/a/16870791/4565796
Saeed Arianmanesh
38

Você pode usar o CountDownTimerque é muito mais eficiente do que qualquer outra solução publicada. Você também pode produzir notificações regulares em intervalos ao longo do caminho usando seu onTick(long)método

Dê uma olhada neste exemplo, mostrando uma contagem regressiva de 30 segundos

   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();
Sufiyan Ghori
fonte
23

Se você usa atraso com frequência em seu aplicativo, use esta classe de utilitário

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.
    }
}

Uso:

// 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
fonte
1
Por quê ? Isso é pura sobrecarga ea complexidade ... para nada
juloo65
Se usarmos atrasos frequentes, é bom ter um formato fixo para atrasos. Eu não acho que exista muita sobrecarga por causa de uma interface adicional e um método.
Aruke
18

Usando o Thread.sleep(millis)método

user2270457
fonte
30
não faça isso no thread UI - outros elementos também pode parar de responder e, posteriormente, se comportam de forma imprevisível
jmaculate
1
obrigado pelo aviso. isso é exatamente o que eu preciso, para atrasar o thread da interface do usuário. resposta perfeita para minhas necessidades. obrigado.
22419
7

Se você deseja fazer algo na interface do usuário em intervalos regulares, a opção muito boa é usar o 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
fonte
É mais limpo que o manipulador .
Ahsan
3

Resposta do manipulador no Kotlin:

1 - Crie uma função de nível superior dentro de um arquivo (por exemplo, um arquivo que contém todas as suas funções de nível superior):

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

2 - Em seguida, ligue para onde você precisar:

delayFunction({ myDelayedFunction() }, 300)
Phil
fonte
2

Você pode usar isto:

import java.util.Timer;

e para o atraso em si, adicione:

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

onde a delayvariável está em milissegundos; por exemplo, definido delaycomo 5000 para um atraso de 5 segundos.

Dror
fonte
0

Aqui está um exemplo em que eu mudo a imagem de fundo de uma para outra com um atraso de desvanecimento alfa de 2 segundos nos dois sentidos - desvanecimento de 2 segundos da imagem original em desvanecimento de 2 segundos na segunda imagem.

    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
fonte