Поток пользовательского интерфейса перестает работать правильно во время выполнения - PullRequest
0 голосов
/ 29 апреля 2019

Я делаю игру для Android с использованием Java.Когда пользователь нажимает кнопку, которая запускает поток, который выполняет кучу бросков и прыжков, которые продолжаются некоторое время с помощью sleep (20) и this.invalidate (), чтобы показать, что это происходит в режиме реального времени.Я также пытаюсь представить поток демона, который будет отвечать за анимацию.Я заметил, что с введением второго потока что-то в потоке пользовательского интерфейса разрывается во время выполнения программы.Как скоро он сломается, зависит от ряда факторов.Но как только он ломается, можно наблюдать следующие вещи:

  • код внутри activity.runOnUiThread (new Runnable () {прекращает выполнение.
  • при переключении на другоеприложение и обратно, панель действий и панель уведомлений больше не исчезают, поэтому выполнение этого кода также прекращается:

    getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
    
  • закрытие приложения и его повторный запуск приводит к его зависанию с пробеломсерый экран.

Однако все равно работает следующее: * анимации по-прежнему отображаются правильно * выстрелы и отскоки по-прежнему работают и отображаются правильно без задержек. * Уничтожение приложения и его повторный запуск временно исправляет его.

Кажется, что следующие сценарии вызывают разрыв во время выполнения:

  1. введение дополнительного потока анимации.

    public void animThread () {

    animThread = new Thread ( new Runnable( ) {
        public void run( )
        {
    
        while(true)
        {
            animation();
        }
    
    
        }
    } );
    
    animThread.setDaemon(true);
    animThread.setPriority(3);
    animThread.start();
    

    }

    private void animation () {if (powerups.isEmpty () == false) {synchronized (powerups) {for (PowerUp pw: powerups) {if (pw.isActivated ()== false) pw.rotate ();}}

    }
    
    this.invalidate();
    
    
    try {
        if(Units.animPause==true)
        {
    
            synchronized (Units.animSync) {
                while (Units.animPause) {
                    try {
                        Units.animSync.wait();
                    } catch (InterruptedException e) {
                        System.out.println("interrupt");
                    }
                }
            }
    
        }
        else {
    
            Thread.sleep(20);                //delay before next cycle
        }
    
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    

    }

Приоритет, демон, оператор if, который проверяет, должен ли поток ждать, не имеет значения.Проблема произойдет без единого вызова activity.runOnUiThread.

Если я вызываю activity.runOnUiThread слишком часто из темы съемки.Та же проблема произойдет даже без анимации.Я даже заменил весь код стрельбы этим, чтобы проверить:

public void testshoot () {// int count = 0;while (counter <100) {</p>

    counter++;
    System.out.println("counter: " + counter);
    if(counter % 2 == 0)
    {
        gw.activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                System.out.println("game over run");
                System.out.println("counter: 1: " + counter);
                gw.activity.findViewById(R.id.GameOver).setVisibility(View.VISIBLE);
                ((TextView)gw.activity.findViewById(R.id.Score)).setText("Your Score: " + counter);
                System.out.println("game over run1");
            }
        });
    }

    try {
        if(Units.isPaused==true)
        {
            synchronized (Units.pauseSync) {
                while (Units.isPaused) {
                    try {
                        Units.pauseSync.wait();
                    } catch (InterruptedException e) {
                        System.out.println("interrupt");
                    }
                }
            }

        }
        else {

            Thread.sleep(20);                //delay before next cycle
        }

    } catch (InterruptedException e) {
        e.printStackTrace();
    }

}

counter=0;

}

Что произойдет, если на экране отобразится меню, и счетчик начнет корректно увеличиваться, пока не произойдетпросто перестает обновляться, потому что код внутри runOnUiThread перестал выполняться, потому что что-то сломалось.Похоже, что повторение звонка откладывает или даже устраняет проблему.Например, если (счетчик% 10 == 0)

Если я объединю поток анимации из пункта 1 с вызовом runOnUiThread из пункта 2, проблема появится раньше.

Мой onPause и onResume:

public void onPause()
{
    if(Units.isPaused == false)
    {
        Units.adHocPause=true;
        synchronized (Units.pauseSync) {
            Units.isPaused = true;
        }
    }

    synchronized (Units.animSync) {
        Units.animPause = true;
    }

    super.onPause();
}

@Override
public void onResume(){
    //System.out.println("is paused: " + Units.isPaused);
    if(Units.adHocPause==true)
    {
        Units.adHocPause=false;
        synchronized (Units.pauseSync) {
            Units.isPaused = false;
            Units.pauseSync.notifyAll();
        }
    }
    else
    {
        View menu = findViewById(R.id.Menu);
        menu.setVisibility(View.VISIBLE);
        synchronized (Units.pauseSync) {
            Units.isPaused = true;
        }
    }

    synchronized (Units.animSync) {
        Units.animPause = false;
        Units.animSync.notifyAll();
    }


    getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
    super.onResume();
}

Я хочу понять, что именно происходит, когда что-то ломается в моем приложении во время выполнения, что ломается, что вызывает это и какмогу ли я избежать этого.Я заинтересован в том, чтобы сценарий 1 работал.Я включил сценарии 2 и 3, потому что, надеюсь, они дают понять, что ломается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...