How to set delay in android?

JavaAndroid

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

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

Solution 2 - Java

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

Solution 3 - Java

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

Solution 4 - Java

Using the Thread.sleep(millis) method.

Solution 5 - Java

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

Solution 6 - Java

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)

Solution 7 - Java

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.

Solution 8 - Java

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

Solution 9 - Java

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.

Solution 10 - Java

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


            }
        });


    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKenneth Joseph PaulView Question on Stackoverflow
Solution 1 - JavaTuan VuView Answer on Stackoverflow
Solution 2 - JavaSufiyan GhoriView Answer on Stackoverflow
Solution 3 - JavaarukeView Answer on Stackoverflow
Solution 4 - Javauser2270457View Answer on Stackoverflow
Solution 5 - JavaIvo StoyanovView Answer on Stackoverflow
Solution 6 - JavaPhilView Answer on Stackoverflow
Solution 7 - JavaDrorView Answer on Stackoverflow
Solution 8 - JavaMuharizJView Answer on Stackoverflow
Solution 9 - JavaSirius BeyView Answer on Stackoverflow
Solution 10 - JavaViraj SawantView Answer on Stackoverflow