2

I'm trying to use a thread on my application to delay that thread without freezing the activity. The problem is that the activity is getting freezed even if i have the Thread.sleep() on the thread. What i want to do is a game like Simon says, i want to hightlight a button for 2 seconds without freezing the activity, but it gets freezed. The thread is called NuevoColor, and i start it at the end of the onCreate method. I'll paste the code here, thanks in advance.

package com.example.simondice;

import java.util.ArrayList;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;

public class Jugar extends Activity {

public Button boton1Rojo;
public Button boton2Azul;
public Button boton3Verde;
public Button boton4Amarillo;

public ArrayList<Integer> arrayJuego; //se guarda la secuencia del juego
public ArrayList<Integer> arrayJugador; //se guarda la secuencia introducida por el jugador

@Override public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.jugar);
    boton1Rojo = (Button) findViewById(R.id.button1);
    boton2Azul = (Button) findViewById(R.id.button2);
    boton3Verde = (Button) findViewById(R.id.button3);
    boton4Amarillo = (Button) findViewById(R.id.button4);

    //cambiamos el color de los botones
    boton1Rojo.setBackgroundColor(Color.rgb(127, 0, 0));
    boton2Azul.setBackgroundColor(Color.rgb(0, 0, 127));
    boton3Verde.setBackgroundColor(Color.rgb(0, 127, 0));
    boton4Amarillo.setBackgroundColor(Color.rgb(127, 127, 0));

    //botones a disable al iniciar
    boton1Rojo.setEnabled(false);
    boton2Azul.setEnabled(false);
    boton3Verde.setEnabled(false);
    boton4Amarillo.setEnabled(false);

    //iniciamos el juego
    NuevoColor juego = new NuevoColor();
    juego.start();
}


// Crea un nuevo color para el juego
public class NuevoColor extends Thread {

    @Override public void run() {
        runOnUiThread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                arrayJuego = new ArrayList<Integer>();

                try {
                    int rand = 0;

                    rand = (int) Math.floor(Math.random()*4+1);

                    if(rand==1) { //iluminamos los botones y los añadimos al array
                        boton1Rojo.setBackgroundColor(Color.rgb(255, 0, 0));
                        arrayJuego.add(1);
                        Thread.sleep(2000);
                        boton1Rojo.setBackgroundColor(Color.rgb(127, 0, 0));
                    } else if(rand==2) {
                        boton2Azul.setBackgroundColor(Color.rgb(0, 0, 255));
                        arrayJuego.add(2);
                        Thread.sleep(2000);
                        boton2Azul.setBackgroundColor(Color.rgb(0, 0, 127));
                    } else if(rand==3) {
                        boton3Verde.setBackgroundColor(Color.rgb(0, 255, 0));
                        arrayJuego.add(3);
                        Thread.sleep(2000);
                        boton3Verde.setBackgroundColor(Color.rgb(0, 127, 0));
                    } else {
                        boton4Amarillo.setBackgroundColor(Color.rgb(255, 255, 0));
                        arrayJuego.add(4);
                        Thread.sleep(2000);
                        boton4Amarillo.setBackgroundColor(Color.rgb(127, 127, 0));
                    }
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }

        });
    }
}

}

Edit: thanks everyone for the answers, now i know better whats runOnUiThread for() . Here's the class working after some changes, just in case someone finds it usefull:

    public class NuevoColor extends Thread {

    @Override public void run() {
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        runOnUiThread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                cambiarColor();
            }

        });

        try {
            Thread.sleep(2000);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        runOnUiThread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                colorOriginal();
            }

        });
    }
}
souanyirer
  • 23
  • 1
  • 4
  • 2
    Using `Thread.sleep(2000)` inside `runOnUiThread` sleep Main UI thread instead of Worker Thread. so Use `Handler` or `AsyncTask` to avoid freezing of UI Thread – ρяσѕρєя K Feb 17 '14 at 10:57

2 Answers2

0

Since you call Thread.sleep(2000) inside runOnUiThread , therefore the UI freezes as pointed out by ρяσѕρєя .Do not call sleep on the ui thread. You should not block the ui thread.

Refer to this Does Thread.sleep() makes the UI Thread to sleep?

Workaround to your problem : Call an async task and inside the async task's doinbackground() call Thread.sleep(2000) .doinbackground() of async task does not run on the UI thread . Here is how you can use async task AsyncTask Android example

Community
  • 1
  • 1
Rachita Nanda
  • 4,509
  • 9
  • 42
  • 66
0

Just move "Thread.sleep(2000);" to outside the Runnable that you run on the UI thread. I see that you want to sleep the thread in any case. So something like this:

public class NuevoColor extends Thread {

    @Override public void run() {
        Thread.sleep(2000);
        runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    // ...
                }

            });
    }
}

Anything that you run inside run() of NuevoColor is tha background work, and sleeping should be there, since you want the background thread to be paused, and not the whole use interface.

Anything insite the Runnable that you throw to runOnUiThread() will, of course, run on the UI thread, so it will freeze the whole user interface until it's done. So no heavy work there, also no sleeping.

In general, think of it like this: anything you want to do, do it in the background thread. Anything that updates the UI, (like setBackgroundColor() etc), run it on the UI thread. In your case just move the Thread.sleep(2000) as I indicated.

Stan
  • 2,151
  • 1
  • 25
  • 33