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.
Using the Thread.sleep(millis)
method.
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();
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
}
});
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);
}
});
}
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.
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)
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();
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.
Source: Stackoverflow.com