Reputation: 2211
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.
Upvotes: 195
Views: 437410
Reputation: 1
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();
}
});
}
}
Upvotes: 0
Reputation: 109
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.
Upvotes: 0
Reputation: 5505
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.
Upvotes: 6
Reputation: 6447
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);
Upvotes: 604
Reputation: 11
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);
}
});
}
Upvotes: 0
Reputation: 4870
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)
Upvotes: 5
Reputation: 621
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
}
});
Upvotes: 28
Reputation: 18719
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();
Upvotes: 8
Reputation: 18753
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();
Upvotes: 48