Перезапуск / приостановка потока в onResume / onPause - PullRequest
7 голосов
/ 15 августа 2011

У меня есть игра, которая использует реализацию SurfaceView для отображения объектов. У меня есть поток, который время от времени рисует SurfaceView на экран. Игра работает полностью. К сожалению, это должно было иметь функцию паузы всякий раз, когда игра прерывается. Ну, я знаю, что мне нужно манипулировать onResume и onPause.

Но я не могу понять это правильно. Ошибка указывает мне обратно на surfaceCreated, где я запускаю поток, сообщая, что поток уже запущен. Я попытался использовать resume и suspend на onResume и onPause соответственно, но ничего не изменилось.

Как мне этого добиться? Я уже сделал, как местоположение объектов будет сохранено с помощью обработки ввода-вывода файла.

Заранее спасибо.

Ответы [ 4 ]

3 голосов
/ 16 августа 2011

Вот что я сделал:

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
           if (thread.getState() == Thread.State.TERMINATED){
              CreateThread(getHolder(),getContext());
           }
           thread.setRunning(true);
           thread.start();
    }
  • В CreateThread у вас должна быть ветка = new MyThread (...);
  • setRunning (булево mRun) использует логическое значение для запуска / остановки функции запуска (я думаю, что меня вдохновил LunarLander);

Если вы хотите правильно использовать onPause / onResume, не помещайте переменные, используемые вашим потоком, в поток (как это сделано в LunarLander). Я предлагаю вам сделать так:

// Variables declarations

public MyGameThread CreateThread(...){
thread = new MyGameThread(holder, context, new Handler() {
// and so on....
});
}

Когда вы проходите через onPause / onResume, ваш поток будет уничтожен и обновлен, но если вы поместите свои переменные вне его, вы можете продолжать использовать их после.

Если вы хотите сохранить что-то важное, используйте один из следующих вариантов:

  • SharedPreferences: xml будет создан и сохранен локально с переменными, которые сохраняются даже после окончания приложения;
  • БД SQL, если вы будете управлять более чем 5-10 переменными, потому что в этом случае использование первого варианта будет затруднено.
2 голосов
/ 15 августа 2011

На самом деле не рекомендуется останавливать поток самостоятельно, метод stop() не рекомендуется. Самое простое решение - использовать флаг в цикле while внутри метода потока run(). Когда вам нужно «остановить» поток, вы просто сбрасываете флаг на false, и поток больше ничего не будет делать, несмотря на то, что он продолжит работать. Android остановит вашу ветку, когда это будет необходимо. Надеюсь, это поможет.

1 голос
/ 25 августа 2011

Не зная все входы и выходы вашего кода.

Чтобы «приостановить» поток, вы можете реализовать такую ​​функцию:

while(! this.isInterrupted())
    if(!paused)
    {
        ... Do something ...
    } else { try { Thread.sleep(100) } catch (InteruptedException ie) {} }

Это зависит от того, является ли Do something недействительнымваш вид поверхности или иным образом контролировать прогресс в вашем приложении.Функция доступа к paused должна позволять вам приостанавливать и возобновлять поток, не увязая в какой-либо другой части архитектуры.

1 голос
/ 25 августа 2011

Я не уверен, если у вас есть один или два потока в этом вопросе, я предполагаю 2. Вам нужно сделать три вещи, когда вы вызываете onPause:

1 - Save the state of the application (all game variables, states, etc)
2 - Kill the surfaceView by calling suspend.
3 - Kill the other thread (we'll call it Thread B).

Уничтожение нити Bэто твоя проблема, я думаю.Вы хотите прервать поток и попросить его выйти, иначе, когда вы вызываете onPause, ваш поток все равно будет делать свое дело.Затем, когда вы вернетесь в игру, поток попытается создать заново, что вызывает проблему.Есть 2 способа правильно завершить поток:

  • В цикле while() вашего потока есть логическое значение 'run', которое while(run) выполнит код.Когда вы изменяете run на false, поток завершается.
  • Если ваш поток спит (я предполагаю, что это может произойти, так как это игра и будет работать без времени), перехватите InterruptedException и затем выйдите.Когда вы хотите уничтожить поток, вы добавляете исключение в поток.

Первый вариант, безусловно, самый простой.

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