How can I programmatically cause a delay in Android?

1.3k views Asked by At

I tried to use Thread.sleep() but it didn't work. When I use it, the app stops responding.

I need to put some delays in my code like this:

public void inicioJogo(){
        for (int jogada = 1; jogada <= 50; jogada++) {
            for (int contador = 0; contador < jogada; contador++){
                // HERE - Wait 1 sec before go to next line.
                btPedra[sequencia[contador]].setBackgroundResource(imagensHover[sequencia[contador]]);
                // HERE - Wait 1 sec before go to next line.
                btPedra[sequencia[contador]].setBackgroundResource(imagensNormal[sequencia[contador]]);
                // Now continue looping.
            }
        }
}

I tried to use Handler, like this:

private Handler handler = new Handler();
    for (int jogada = 1; jogada <= 50; jogada++) {
        for (int contador = 0; contador < jogada; contador++){
            handler.postDelayed(new Runnable () {
                @Override
                public void run() {
                    btPedra[sequencia[contador]].setBackgroundResource(imagensHover[sequencia[contador]]);
                }
            }, 1000);
        }
    }

But when I use it, the looping continue before waiting 1 sec. I need a delay that can stop the looping for 1 sec, go to the next line, and after that continue looping.

2

There are 2 answers

1
Simas On BEST ANSWER

The reason why it doesn't respond is because you call sleep on the current thread. And the current thread you're dealing with is the UI thread. So basically you try to change the background and then sleep the thread preventing it to actually be changed until the sleeps are done.

You need to run your loop in another thread and sleep there so it doesn't affect the main thread:

final Handler handler = new Handler();
new Thread(new Runnable() {
    @Override
    public void run() {
        for (int jogada = 1; jogada <= 50; jogada++) {
            for (int contador = 0; contador < jogada; contador++){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        btPedra[sequencia[contador]].setBackgroundResource(imagensHover[sequencia[contador]]);
                    }
                });
            }
        }
    }
}).start();

Note that the background change is done via the handler you create before starting the new thread. That handler is created on the current thread, which is the UI thread, and every message posted to it will run on that thread.

So basically you loop and wait on another thread but do the background changing on the UI thread.

0
Logic On

You can use ScheduledExecutorService like

ScheduledExecutorService scheduledExecutorService =
    Executors.newScheduledThreadPool(NO_OF_THREADS);

ScheduledFuture scheduledFuture =
    scheduledExecutorService.schedule(task, NO_OF_SECONDS_TO_WAIT, TimeUnit.SECONDS);

and now the "task" executes after a delay of NO_OF_SECONDS_TO_WAIT