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

        }
    }

I want to set a delay between the command between changing background. I tried using a thread timer and tried using run and catch. But it isn't working. I tried this

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

But it is only getting changed to black.

Kenneth Joseph Paul
  • 2,171
  • 2
  • 14
  • 27

10 Answers10

599

Try this 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);
Yingchen
  • 370
  • 5
  • 14
Tuan Vu
  • 6,397
  • 2
  • 14
  • 22
  • 1
    This solution explained all the questions that I had with handlers at some lines of code. – Sierisimo May 19 '15 at 17:55
  • 76
    I always come back to this post because I am too lazy to write it every time. Thank you. – Eugene H Jan 06 '16 at 18:54
  • well it llok nice but i have lots of message to wait then show. so multible treads give problem. how can solve multiple treads problem – mehmet Dec 22 '16 at 08:41
  • 2
    This solution produces a memory leak because it uses a non-static inner and anonymous class which implicitly holds a reference to its outer class, the activity. See https://stackoverflow.com/questions/1520887/how-to-pause-sleep-thread-or-process-in-android/3039718#3039718 for a better solution. – tronman Aug 25 '17 at 15:03
  • @EugeneH Use Live Templates for easier life https://stackoverflow.com/a/16870791/4565796 – Saeed Arianmanesh Aug 31 '19 at 07:09
  • Suppose this code is inside a function. The function is being invoked from onCreate(). There are lines after the function call statement. So, will the control return from the function and then execute the statements after function call statement or will it be asynchronously executed? – Samudra Ganguly Sep 29 '20 at 12:15
  • 1
    This is deprecated now. – Andrew Feb 17 '21 at 14:38
46

You can use CountDownTimer which is much more efficient than any other solution posted. You can also produce regular notifications on intervals along the way using its onTick(long) method

Have a look at this example showing a 30seconds countdown

   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
  • 18,164
  • 14
  • 82
  • 110
  • Why is `CountDownTimer` more efficient than `Handler.postDelayed` is explain in https://stackoverflow.com/q/35497844/2597758 – WebViewer Jan 12 '23 at 14:52
27

If you use delay frequently in your app, use this utility class

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
  • 611
  • 1
  • 10
  • 17
  • 2
    Why ? This is pure overhead and complexity... for nothing – juloo65 Jul 08 '18 at 23:54
  • 1
    If we use frequent delays, then having a fixed format for delays is fine. I don't think there is much overhead because of one additional interface and a method. – aruke Jul 18 '18 at 01:52
  • With lambda this solution becomes really clean and simple. Utils.delay(2, () -> {// Do something after delay}); – C. Skjerdal Oct 24 '21 at 16:58
25

Using the Thread.sleep(millis) method.

geisterfurz007
  • 5,292
  • 5
  • 33
  • 54
user2270457
  • 325
  • 2
  • 3
  • 39
    do not do this on the UI thread -- other elements may also stop responding and later behave unpredictably – jmaculate May 19 '14 at 18:23
  • 1
    thanks for the warning. thats exactly what I need, to delay the UI thread. perfect answer for my needs. thanks. – hamish Jun 06 '14 at 20:15
8

If you want to do something in the UI on regular time intervals very good option is to use 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
  • 16,256
  • 8
  • 62
  • 65
6

You can use this:

import java.util.Timer;

and for the delay itself, add:

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

where the delay variable is in milliseconds; for example set delay to 5000 for a 5-second delay.

auspicious99
  • 3,902
  • 1
  • 44
  • 58
Dror
  • 5,107
  • 3
  • 27
  • 45
5

Handler answer in Kotlin :

1 - Create a top-level function inside a file (for example a file that contains all your top-level functions) :

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

2 - Then call it anywhere you needed it :

delayFunction({ myDelayedFunction() }, 300)
Phil
  • 4,730
  • 1
  • 41
  • 39
0

Here's an example where I change the background image from one to another with a 2 second alpha fade delay both ways - 2s fadeout of the original image into a 2s fadein into the 2nd 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
  • 11
  • 2
0

I think the easiest and most stable and the most useful way as of 2020 is using delay function of Coroutines instead of Runnable. Coroutines is a good concept to handle asynchronous jobs and its delay component will be this answer's focus.

WARNING: Coroutines need Kotlin language and I didn't convert the codes to Kotlin but I think everybody can understand the main concept..

Just add the Coroutines on your build.gradle:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'

Add a job to your class (activity, fragment or something) which you will use coroutines in it:

private var job: Job = Job()
override val coroutineContext: CoroutineContext
    get() = Dispatchers.Main + job

And you can use Coroutines anywhere on the class by using launch{ } body. So you can write your code like this:

public void onClick(View v) {

    launch {

        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);
                        delay(2000)
                        buttons[inew][jnew].setBackgroundColor(Color.WHITE);
                        break;
                    }
                }
        }
            break;

        }
    }
}

It's All...

Dont't forget that launch{} function is asynchronous and the for loop will not wait for delay function to finish if you write like this:

launch{
    buttons[inew][jnew].setBackgroundColor(Color.BLACK);
    delay(2000)
    buttons[inew][jnew].setBackgroundColor(Color.WHITE);
}

So, launch{ } should cover the for loop if you want all the for loop to wait for delay.

Another benefit of launch{ } is that you are making the for loop asynchronous, which means it is not gonna block the main UI thread of the application on heavy processes.

Sirius Bey
  • 109
  • 5
0
package com.viraj.myamppractice;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.Random;

public class Question6 extends AppCompatActivity {

    TextView diceop;
    Button roll;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_question6);

        roll = findViewById(R.id.rollButton);
        diceop = findViewById(R.id.opDice);
        Thread timer = new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    Random no = new Random();
                    int number = no.nextInt(6)+1;
                    String str = String.valueOf(number);

                    diceop.setText(str);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        roll.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                timer.run();


            }
        });


    }
}
  • This java code is an better alternative to it – Viraj Sawant Apr 04 '22 at 01:27
  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 04 '22 at 03:29