Search code examples
javaandroidtimertaskandroid-handlerjava-threads

How can I programmatically cause a delay in Android?


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.


Solution

  • 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.