"Hilo ya iniciado" al reanudar la actividad

Aquí está mi situación: Estoy construyendo un juego para android y la actividad de mi juego está compuesta por una superficie de vista personalizada que tiene un hilo para la lógica del juego y la representación. La arquitectura es similar a la demostración LunarLander del sitio web de Google.

Cuando se inicia la actividad, crea el surfaceView y llama a este método:

@Override public void surfaceCreated(SurfaceHolder holder) { renderThread.start(); } 

Cuando presiono el botón de inicio para salir del juego, se llama al método onPause (), que llama a surfaceDestroyed (). En surfaceDestroyed detengo el juego Thread llamando al:

  @Override public void surfaceDestroyed(SurfaceHolder holder) { synchronized(holder) { renderThread.stop(); } } 

La aplicación va a fondo bien. Luego, cuando vuelva a iniciar la aplicación pulsando el icono, obtendré un mensaje "Hilo ya iniciado" en el registro junto con una ventana emergente de "cierre de la fuerza" en la pantalla. Este mensaje ocurre cuando la actividad entra en el método "surfaceCreated" cuando llama a start () en el subproceso de procesamiento.

Ahora he mirado en él por horas y no puedo entender por qué esto es. Creo que mi hilo se detiene cuando cierro la aplicación por lo que no entiendo por qué dice que ya ha comenzado.

Esos métodos no hacen lo que crees que hacen. Desde el Documento del API :

Nunca es legal iniciar un hilo más de una vez.

Y:

public final void stop() – Deprecated. Este método es inherentemente inseguro.

Si desea pausar un subproceso, tiene que utilizar Object.wait() y Objecft.notifyAll() de dentro del subproceso.

En mi opinión, no deberías empacar tu código en una subclase de Thread si tienes intención de iniciar y detener el hilo a menudo (los ejemplos lo hacen porque hace que el código sea más corto). Utilice un Runnable en su lugar. De esta manera puede detener y descartar el hilo antiguo cuando quiera y crear un nuevo objeto Thread para ejecutar el Runnable cuando necesite iniciarlo de nuevo.

 private TutorialRunnable tutorialRunnable; ... // Synchronization and error checking omitted for brevity. public void surfaceCreated(SurfaceHolder holder) { thread = new Thread(tutorialRunnable); thread.start(); } public void surfaceDestroyed(SurfaceHolder holder) { tutorialRunnable.setRunning(false); while (thread != null) { try { thread.join(); thread = null; } catch (InterruptedException e) { } } } 

También, confiar en excepciones es mala forma. Que debe utilizarse como un último recurso cuando su propio código se comporta inesperadamente.

Una mala solución, pero funciona.

  public void surfaceCreated(SurfaceHolder holder) { try{ _thread.setRunning(true); _thread.start(); }catch(Exception ex){ _thread = new TutorialThread(getHolder(), this); _thread.start(); } } 

Correcciones son bienvenidos.

  • Uso adecuado de yieldIfContendedSafely () en una aplicación multithreaded de Android
  • Múltiples hilos de lectura desde el mismo socket
  • ¿Cómo utilizar ExecutorService con Android AsyncTask?
  • Android - ¿cómo pasar los datos al Runnable en runOnUiThread?
  • ¿Cómo esperar que todas las tareas en un ThreadPoolExecutor terminen sin apagar el Ejecutor?
  • Thread.join con un patrón de "reintento"
  • Ejecutar código en el hilo principal desde otro hilo
  • La mejor manera de ejecutar el método asincrónicamente en Android (compacto y correcto)
  • Android: CursorLoader, LoaderManager, SQLite
  • ¿Cómo ejecutar el servicio no en el hilo principal?
  • Diferencia entre MainThread, UiThread, WorkerThread, BinderThread en Android Annotation
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.