2011-05-16 33 views
6

Estoy implementando una subclase SurfaceView, donde ejecuto un hilo separado para dibujar en un lienzo SurfaceHolders. Estoy midiendo el tiempo antes y después de llamar al lockCanvas(), y estoy obteniendo de aproximadamente 70 ms a 100 ms. ¿Alguien podría indicarme por qué estoy recibiendo horarios tan altos? Aquí la parte pertinente del código:¿Por qué es lento LockCanvas()?

public class TestView extends SurfaceView implements SurfaceHolder.Callback { 

.... 

boolean created; 
public void surfaceChanged(SurfaceHolder holder, int format, int width, 
      int height) { 

    mThread = new DrawingThread(mHolder, true); 
    mThread.onWindowResize(width, height); 
    mThread.start(); 
} 

public void surfaceCreated(SurfaceHolder holder) { 

    created = true; 
} 

public void surfaceDestroyed(SurfaceHolder holder) { 
    created = false; 

} 
class DrawingThread extends Thread { 
public void run() { 
while(created) { 



      Canvas canvas = null; 
      try { 
          long t0 = System.currentTimeMillis(); 
      canvas = holder.lockCanvas(null); 
      long t1 = System.currentTimeMillis(); 
          Log.i(TAG, "Timing: " + (t1 - t0)); 
      } finally { 
       holder.unlockCanvasAndPost(canvas); 
      } 
} 

Respuesta

1
+0

Ok, gracias. Ya lo he leído antes y entiendo los conceptos. Pero todavía no encuentro una solución. Incluso si elimino el bloque 'synchronized' (que no se recomienda), no me ayuda. Aún esos tiempos altos. – kaneda

4

Estás creando un hilo cada vez que se cambia la superficie. Deberías comenzar tu hilo en surfaceCreated y matarlo en surfaceDestroyed. surfaceChanged es para cuando cambian las dimensiones de su superficie.

Desde SurfaceView. surfaceCreated documentos:

Esto se invoca inmediatamente después de que se crea la superficie por primera vez. Las implementaciones de esto deben iniciar cualquiera que sea el código de representación que deseen. Tenga en cuenta que solo un hilo puede dibujar en una Superficie, por lo que no debe dibujar en la Superficie aquí si su renderizado normal estará en otro hilo.

Los hilos múltiples probablemente lo estén acelerando. De SurfaceHolder. lockCanvas docs:

Si se llama a esto en varias ocasiones cuando la superficie no está listo (antes o después de Callback.surfaceCreated Callback.surfaceDestroyed), sus llamadas serán estrangulados a una velocidad lenta con el fin de evitar el consumo de CPU.

Sin embargo, no estoy seguro de que este sea el único problema. ¿Se llama realmente surfaceChanged varias veces?

+0

Cuando los documentos dicen 'solo un hilo puede dibujar en una superficie' ... se debe tomar esta afirmación al pie de la letra, o dicen" ... alguna vez puede dibujar en una superficie * al mismo tiempo * ". –

+1

Creo que se debe tomar al pie de la letra. Incluso si no es así, entonces debes manejar la serialización de tus comandos de dibujo. (Que es probablemente la razón por la que requieren que los envíe en un solo hilo.) De acuerdo con http://stackoverflow.com/a/11258546/79125 estoy en lo cierto (pero somos solo dos tipos en Internet;). – idbrii

+0

ooh. Definitivamente soy aficionado a un buen tutorial (al que se vincula esa respuesta). Gracias. Desearía poder darte dos + 1 por eso =) –

1

Esto se relaciona con la forma en que lockCanvas se implementa realmente en el marco gráfico de Android.

Probablemente ya sepa que lockCanvas le devolverá una pieza gratuita que se utilizará para dibujar. Por gratis, significa que esta memoria no se debe usar para composición y no para visualización. Internamente, simplemente hablando, un SurfaceView está respaldado por doble buffer, uno es para dibujar, uno es para composición/visualización. Este buffer doble es administrado por BufferQueque. Si la composición/visualización es lenta que el dibujo, tenemos que esperar hasta que tengamos un buffer libre disponible.