线程正在冻结Android应用程序上的活动

时间:2014-02-17 10:53:48

标签: android multithreading

我正在尝试在我的应用程序上使用一个线程来延迟该线程而不冻结活动。问题是,即使我在线程上有Thread.sleep(),活动也会被冻结。我想做的是像西蒙这样的游戏,我想要点亮一个按钮2秒而不冻结活动,但它会被冻结。该线程称为NuevoColor,我在onCreate方法的末尾启动它。我会在这里粘贴代码,提前谢谢。

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();
                }

            }

        });
    }
}

}

编辑:感谢大家的答案,现在我知道更好的是runOnUiThread for()。这是在一些变化后工作的类,以防有人发现它有用:

    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();
            }

        });
    }
}

2 个答案:

答案 0 :(得分:0)

由于你在runOnUiThread中调用Thread.sleep(2000),因此UI会因ρяσѕρєя指出而冻结。不要在ui线程上调用sleep。你不应该阻止ui线程。

请参阅Does Thread.sleep() makes the UI Thread to sleep?

解决您的问题的方法:调用async task并在异步任务的doinbackground()内调用异步任务的Thread.sleep(2000).doinbackground()不在UI上运行线程。以下是如何使用异步任务AsyncTask Android example

答案 1 :(得分:0)

移动“Thread.sleep(2000);”在UI线程上运行的Runnable外部。我知道你想在任何情况下都要睡觉。所以像这样:

public class NuevoColor extends Thread {

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

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

            });
    }
}

你在NuevoColor的run()中运行的任何东西都是后台工作,并且应该在那里休眠,因为你想要暂停后台线程,而不是整个使用界面。

当你在runnable上运行runnable时,运行runOnThread()当然会在UI线程上运行,所以它会冻结整个用户界面,直到完成为止。所以那里没有繁重的工作,也没有睡觉。

一般来说,想到这样:你想做的任何事情,在后台线程中做。任何更新UI的东西(比如setBackgroundColor()等)都会在UI线程上运行它。在你的情况下,按照我的指示移动Thread.sleep(2000)。