2009-03-23 15 views
5

Actualmente estoy familiarizado con Android, jugando con la muestra Lunar Lander.Android: Recuperando el foco usando SurfaceView

He descubierto que si navega fuera de la aplicación (por ejemplo, pulsa el botón de llamada) destruirá la superficie subyacente (llamando al surfaceDestroyed).

navegando hacia atrás (que activará onWindowVisibilityChanged) la aplicación se bloqueará, ya que tratará de dibujar a la superficie sin volver a crearla.

¿Hay algún código que pueda poner en onWindowVisibilityChanged (o en cualquier otro lugar) que regenere la superficie subyacente de SurfaceView y reanude la ejecución correctamente?

Parece que esto debería ser una llamada a una función simple, pero no puedo encontrar nada en los documentos de la API.

Gracias!

Respuesta

1

¡Error de diagnóstico! La aplicación vuelve a crear la superficie automáticamente, pero hay una llamada que intenta dibujar antes de que se cree.

La fijación del problema:

boolean mSurfaceExists; 
... 
public void surfaceDestroyed(SurfaceHolder holder) { 
    mSurfaceExists = false; 
    ... 
} 

public void surfaceCreated(SurfaceHolder holder) { 
    mSurfaceExists = true; 
    ... 
} 

protected void onWindowVisibilityChanged(int visibility) { 
    // only call base if there's a surface 
    if(mSurfaceExists) 
     super.onWindowVisibilityChanged(visibility); 
} 

Ahora todo oleaje. (hasta donde yo sé, de todos modos, los expertos en Java/Android pueden comentar si esta es una mala práctica)

+0

He intentado esto y no dibuja el juego lunar lander correctamente. Todo lo que obtienes es el texto, no la nave espacial o el fondo. –

2

Esta solución para "mSurfaceExists = true" tampoco funciona para mí. Parece que no se llama a surfaceCreated() porque no se llama a super.onWindowVisibilityChanged(). Por lo tanto, no se crea ninguna superficie y no se bloquea porque threas.start no se llama.

Creo que el problema es: Llamar a thread.start() provoca el error porque el hilo ya se inició. Pero en surfaceDestroyed(), thread.join hace que el hilo se complete y muera. Y un hilo no se puede reiniciar una vez muerto.

Supongo que el truco es crear un nuevo subproceso en surfacecreated o hacer que el subproceso se complete solo cuando el usuario está llamando a la aplicación para finalizar (tecla de retroceso) y no pausar (tecla de inicio). Esto se puede verificar llamando a isFinishing() en la actividad.

No estoy seguro si esto funcionará. Intentaré esto pronto.

+0

Acaba de probar (lo depuró) y lo es, como suponía. 'surfaceDestroyed()' se invoca tan pronto como la aplicación se oculta y el hilo se detiene. Al volver a mostrar la aplicación, se invoca 'surfaceCreated()' e intenta iniciar el hilo nuevamente, lo que da como resultado 'IllegalThreadStateException'. – Ridcully

Cuestiones relacionadas