【问题标题】:Thread.sleep of main thread is freezing the app, android [duplicate]主线程的Thread.sleep正在冻结应用程序,android [重复]
【发布时间】:2018-02-26 05:05:18
【问题描述】:

所以问题是我想为我的作业模仿冒泡排序算法的过程。我想要这样做的方式是 - 播放第一个淡出动画,然后停止我的 for 循环,等到动画完成,重新分配值,播放第二个动画,等到它完成并恢复 for 循环。我找到了Thread.sleep(),但最后我的应用程序冻结或屏幕变黑,直到所有动画都完成。我做了很多实验,所以我的代码看起来很糟糕(抱歉)。

public class BubbleSort extends AppCompatActivity {

    Button element1;
    Button element2;
    Animation fadeIn;
    Animation fadeOut;
    int[] values;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bubble_sort);

        fadeIn = AnimationUtils.loadAnimation(getApplicationContext(),
                R.anim.fade_in);
        fadeOut = AnimationUtils.loadAnimation(getApplicationContext(),
                R.anim.fade_out);

    }


    public void onSort(View view){
        HashMap<Integer, Integer> indexes = sort();
        Set<Integer> keySet = indexes.keySet();
        Integer[] keys  =  keySet.toArray(new Integer[keySet.size()]);
        for (int key : keys) {
            initElements(key, indexes.get(key));
            element1.startAnimation(fadeOut);
            element2.startAnimation(fadeOut);
            try {
                Thread.sleep(2000);
                element1.startAnimation(fadeIn);
                element1.setText("" + values[key]);
                element2.startAnimation(fadeIn);
                element2.setText("" + values[indexes.get(key)]);
            } catch (Exception e) {
                Log.i("test", e.toString());
            }
        }
    }

    void initElements(int from, int to){
        switch (from){
            case 0:{
                element1 = (Button) findViewById(R.id.element_1);
                break;
            }
            case 1:{
                element1 = (Button) findViewById(R.id.element_2);
                break;
            }
            case 2:{
                element1 = (Button) findViewById(R.id.element_3);
                break;
            }
            case 3:{
                element1 = (Button) findViewById(R.id.element_4);
                break;
            }
            case 4:{
                element1 = (Button) findViewById(R.id.element_5);
                break;
            }
            case 5:{
                element1 = (Button) findViewById(R.id.element_6);
                break;
            }
            case 6:{
                element1 = (Button) findViewById(R.id.element_7);
                break;
            }
            case 7:{
                element1 = (Button) findViewById(R.id.element_8);
                break;
            }
            case 8:{
                element1 = (Button) findViewById(R.id.element_9);
                break;
            }
            case 9:{
                element1 = (Button) findViewById(R.id.element_10);
                break;
            }
            default:{
                element1 = null;
                break;
            }
        }

        switch (to){
            case 0:{
                element2 = (Button) findViewById(R.id.element_1);
                break;
            }
            case 1:{
                element2 = (Button) findViewById(R.id.element_2);
                break;
            }
            case 2:{
                element2 = (Button) findViewById(R.id.element_3);
                break;
            }
            case 3:{
                element2 = (Button) findViewById(R.id.element_4);
                break;
            }
            case 4:{
                element2 = (Button) findViewById(R.id.element_5);
                break;
            }
            case 5:{
                element2 = (Button) findViewById(R.id.element_6);
                break;
            }
            case 6:{
                element2 = (Button) findViewById(R.id.element_7);
                break;
            }
            case 7:{
                element2 = (Button) findViewById(R.id.element_8);
                break;
            }
            case 8:{
                element2 = (Button) findViewById(R.id.element_9);
                break;
            }
            case 9:{
                element2 = (Button) findViewById(R.id.element_10);
                break;
            }
            default:{
                element2 = null;
                break;
            }
        }
    }

    HashMap<Integer, Integer> sort(){
        HashMap<Integer, Integer> indexes = new HashMap<>();
        values = new int[10];
        boolean sorting = true;
        int loop = 1;
        Random random = new Random();

        for (int index = 0; index < values.length; index++){
            values[index] = random.nextInt(10);
        }

        int offset = 0;
        while (sorting){

            System.out.println("To sort:");
            for (int element : values)
                System.out.print(" " + element);
            System.out.println();

            sorting = false;
            for (int index = 0; index < values.length - 1 - offset; index++) {
                if (values[index] > values[index + 1]) {
                    int temp = values[index];
                    values[index] = values[index + 1];
                    values[index + 1] = temp;
                    sorting = true;
                    indexes.put(index, index + 1);
                }
            }

            System.out.println("Loop: " + loop);

            for (int element : values)
                System.out.print(" " + element);
            System.out.println();

            loop++;
            offset++;
        }
        return indexes;
    }
}

【问题讨论】:

  • 如果你让你的主线程休眠,那意味着你的应用程序当然会冻结。

标签: android android-animation


【解决方案1】:

从不在主线程上使用Thread.sleep。主线程是主线程(显然),所以在主线程上休眠是 Android 操作系统将其视为 A 应用程序 Not R如果你睡得太久,就会做出反应。一般来说,如果可以的话,你应该避免阻塞主线程上的任务。

使用第二个线程能够休眠。您可以使用新的 Thread 实例或使用 AsyncTask。

同样适用于runOnUiThread(在不同线程的主线程上运行):切勿使用 Thread.sleep。您的应用程序将获得 ANR,因为您阻止了主线程执行。如果您想在继续之前休眠 2 秒,请使用不同的线程 (you can read more about it here)


自定义线程的一个例子是创建一个新类(尽管您也可以创建一个匿名类):

public class HelloThread extends Thread {
    boolean running;
    //Constructor to get variables. 
    public void run() {
        while(running){
            //While loop is optional, if you have for an instance a game thread you need a while-loop
            //to keep executing the code
        }
    }

    public void setRunning(boolean running){
        this.running = running;
    }

}

或者如我之前所说,匿名类:

Thread t = new Thread(){
    @Override
    public void run() {
        super.run();
        //It is harder to get variables into here though. Declare a "running" boolean
        //In the class if you want repetitive execution
    }
 };

【讨论】:

    【解决方案2】:

    在主线程中使用Thread.sleep()导致应用程序冻结,使用动画回调如下:

    fadeIn = AnimationUtils.loadAnimation(getApplicationContext(),
                R.anim.fade_in);
    fadeIn.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
    
            }
    
            @Override
            public void onAnimationEnd(Animation animation) {
    
            }
    
            @Override
            public void onAnimationRepeat(Animation animation) {
    
            }
        });
    

    【讨论】:

      猜你喜欢
      • 2014-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多