Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I delay a method in a for loop in java?

I am having trouble delaying the method assign_backgrounds() within a for loop. I am trying to create a Simon says game, but instead of delaying and showing the next button that "Simon" presses, it shows all the buttons at once. Any help here would be greatly appreciated. Thanks.

boolean simonsTurn = true;
int x = 4;
int s;
int delay = 1000;
int array_values[] = new int[]{1,2,3,4};


public void simonSays() {
    // running = true;
    if (simonsTurn == true) {
        go();

        for (int i = 0; i < x; i++) {
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                public void run() {
                    go();
                }
            }, 1000);
        }            
    }
}

public void go(){
    s = random_int_between(0,3);
        assign_backgrounds(array_values[s]);
}

public void assign_backgrounds( int array_values ){

    Handler handler = new Handler();

    if( array_values == 1){
        button1_.invalidate();
        button1_.setBackgroundResource(R.drawable.goatclicked);
        button1_.refreshDrawableState();

        handler.postDelayed(new Runnable(){
        public void run(){
        button1_.invalidate();
        button1_.setBackgroundResource(R.drawable.goat);
        button1_.refreshDrawableState();}}, 1000);
        }
    else if( array_values == 2){
        button2_.invalidate();
        button2_.setBackgroundResource(R.drawable.pigclicked);
        button2_.refreshDrawableState();

        handler.postDelayed(new Runnable(){
            public void run(){
                button2_.invalidate();
                button2_.setBackgroundResource(R.drawable.pig);
                button2_.refreshDrawableState();}}, 1000);
    }
    else if( array_values == 3){
        button3_.invalidate();
        button3_.setBackgroundResource(R.drawable.chickenclicked);
        button3_.refreshDrawableState();

        handler.postDelayed(new Runnable() {
            public void run() {
                button3_.invalidate();
                button3_.setBackgroundResource(R.drawable.chicken);
                button3_.refreshDrawableState();}}, 1000);
    }
    if( array_values == 4) {
        button4_.invalidate();
        button4_.setBackgroundResource(R.drawable.cowclicked);
        button4_.refreshDrawableState();

        handler.postDelayed(new Runnable(){
            public void run(){
                button4_.invalidate();
                button4_.setBackgroundResource(R.drawable.cow);
                button4_.refreshDrawableState();}}, 1000);
    }
}
like image 831
Chris Sellman Avatar asked Nov 10 '22 12:11

Chris Sellman


1 Answers

It's because you are creating handlers very fast and then they are all starting at the same time. You should look into how Handler's work and about Asyncronous/Background tasks.

Now back to your problem, you are calling the a loop and it is creating handlers all in a row and they are being created very fast (nanoseconds). They will then all launch 1 second from that creation time because of your postDelayed() call. This is why everything is popping up at the same time! All of these delay posts are being executed at almost the same time on concurrent background threads.

Instead of a for(int i,...) loop you want to have a global int i, just add it to the top of the file.

At the end of any of Simon's turn you'll want, inside of the if, else if statement inside assign_background (at the end of the Runnables, then you'll want to call go().

This might cause problems because you are trying to access the main thread from all these background threads. so you might have to call the function runOnMainUIThread() as a quick hack when you call the go function.

All in all, you are going to have some problems until you understand Handlers, Background Processes, and Threads. Definitely great knowledge to learn about and Android has solid documentation on it just FYI.

like image 184
napkinsterror Avatar answered Nov 14 '22 22:11

napkinsterror