Android - Завершение активности из потока рендеринга - PullRequest
3 голосов
/ 29 ноября 2010

Добрый день.

Я не знаком с жизненным циклом активности в Android и читал как можно лучше, но я не могу понять, как решить следующую проблему хорошим способом.

У меня есть действие с GLSurfaceView для рисования различных вещей на экране. В потоке рендеринга для этого GLSurfaceView я выполняю весь рендеринг, а также реальную логику обновления (в конце я выделю это).

Проблема, с которой я столкнулся, связана с одним из «экранов», нарисованных внутри рендерера. Я хочу завершить действие и заставить его вызывать различные методы жизненного цикла.

Обычно я могу сделать это с System.exit (0); однако завершение действия таким образом, похоже, не вызывает OnStop (); OnDestroy (); методы.

Может быть, я просто глуп и не вижу простого способа сделать это, но есть ли способ получить доступ к Activity и вызвать activity.finish (); без необходимости передавать ссылку на него до конца?

Вероятно, это не вопрос андроида, а скорее проблема Java? Извините, я немного заржавел. Возможно, если бы кто-то мог примерно объяснить, как они справляются с такой проблемой в своем приложении.

Ответы [ 3 ]

5 голосов
/ 29 ноября 2010

Вам необходимо соблюдать правила безопасности потока и не вызывать activity.finish () непосредственно из вашего потока рендеринга. Лучший способ справиться с этим - отправить работоспособный объект обратно в очередь событий для потока пользовательского интерфейса. И пусть этот Runnable вызовет activity.finish ().

Вам не нужно передавать упражнение в ту область, где вы планируете его остановить. Вот что я сделаю. Передайте действие классу, который вы создаете в onCreate (). Что-то вроде:

public void onCreate( ... ) {
   MyRenderer renderer = new MyRenderer( glSurface, this );
}

Тогда внутри MyRenderer я бы сделал что-то вроде:

public void someMethodInRenderer() {
   if( stop ) {
      stop();
   }
}

public void stop() {
   Handler handler = new Handler();
   handler.post( new Runnable() {
      public void run() {
         activity.finish();
      }
   } );
}

Обратите внимание на обработчик, используемый для отправки обратно в поток пользовательского интерфейса. Это позволяет безопасно вызывать activity.finish (). Я не смог найти какую-либо конкретную информацию в документах о том, что безопасно или небезопасно вызывать finish () из другого потока, чтобы быть в безопасности после публикации.

Что нужно иметь в виду. Если someMethodInRenderer () глубоко в недрах вашей программы, вам не нужно иметь доступ напрямую к экземпляру действия. Вам просто нужна ссылка, чтобы что-то, что в конечном итоге вызывает действие, чтобы закончить. Так что, возможно, есть ссылка на другую часть системы, которую вы передаете этому методу, где вы можете добавить stop (). Поэтому stop () и someMethodInRenderer () могут находиться в одном классе или в разных классах. Это выбор, который вы должны сделать. В конце концов, это проблема архитектуры, которую вы должны решить.

1 голос
/ 16 декабря 2013

Чтобы решить проблему, с которой я столкнулся:

Если вы завершаете свою деятельность (в том числе из другого потока) с помощью activity.finish(), важно, чтобы метод потока вывода onDraw() не был заблокирован (произошло со мной из-за моей реализации рендеринга с двойным буфером).

В этом случае был вызван только метод onPause() в классе активности.Методы onStop() и onDestroy() не были вызваны, даже если приложение завершило работу с небольшой задержкой.

Надеюсь, что это поможет всем, кто столкнулся с той же проблемой.

Редактировать: Причина была в том, что в моем activity.onPause() методе я вызывал glSurfaceView.onPause(), а поток рендеринга onDraw() был заблокирован.

1 голос
/ 29 ноября 2010

Если поток рендерера находится внутри Activity, вы можете использовать ActivityClassName.this.finish ();

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