2011-02-23 12 views
14

Probando mi juego en un dispositivo más lento (Orange San Francisco aka ZTE Blade) y he estado obteniendo una velocidad de cuadros espantosa.lockCanvas() realmente lento

que poner un poco de código de depuración en el bucle de tracción y descubrió la siguiente línea se hace cargo de 100 ms:

c = mSurfaceHolder.lockCanvas(); 

Alguien más ve este comportamiento? He reemplazado temporalmente la vista de superficie extendiendo View e implementando onDraw(), y obtuve un mucho mejor framerate.

Aunque en general SurfaceView es mucho más rápido en mi HTC Desire. Sospecho que este puede ser un problema de Android 2.1. Estoy considerando rootear el teléfono y actualizarlo a 2.2 si es posible, pero quería un dispositivo que se ejecutara en 2.1, por lo que podría ser contraproducente a largo plazo.

** ** actualización

He estado trabajando en esto un poco más, y he descubierto algunos aspectos más desconcertantes a ella.

Arreglé el teléfono e instalé 2.2 y el problema todavía ocurre. Cuando se inicia la aplicación por primera vez, lockCanvas está funcionando como se esperaba (0-1 ms). Luego, en algún momento durante mi inicialización, lockCanvas de repente comienza a tomar aproximadamente 100 ms.

Podría valer la pena señalar que estoy cargando mis activos en una tarea Async, de modo que pueda mostrar una pantalla de carga.

A pesar de mis mejores esfuerzos para determinar qué está haciendo realmente el programa cuando ocurre la lentitud, no pude hacerlo. De hecho, cuando lo ejecuto en modo de depuración y en un solo paso, ¡funciona rápido!

Ahora descubrí que si agrego un retraso en el constructor de mi SurfaceView (de aproximadamente 10 segundos), la lentitud no ocurre y todo funciona bien.

Sin embargo, si presiona Inicio y luego vuelve, la lentitud vuelve.

¡Estoy casi al límite de este estúpido problema ilógico! Tengo la intención de atribuirlo a un problema específico del dispositivo.

Creo que podría tener algo que ver con el uso de la memoria. Tal vez algo se está intercambiando y afecta el video ram?

Me interesarían las teorías al menos.

+0

Describa qué controles * cuando * se produce la representación ... ¿está utilizando un hilo dedicado, o invalida() al final de cada dibujo(), o utiliza un mecanismo de tiempo, o qué? –

+0

I usando un hilo para dibujar (de la misma manera que SpriteMethodTest). Solo bucle mientras es cierto. – Kevin

+0

¿Es posible que se quede atrapado en un gran GC? Quiero decir que estoy de acuerdo en que lockCanvas() no es la llamada más barata, pero no debería demorar tanto.Sin embargo, si se quedara atrapado en un GC durante la llamada durante la espera, la llamada parecería tardar 100 ms más de lo que debería. ¿Tienes un logcat o algunos ejemplos de código? –

Respuesta

11

Sobre lockCanvas() a partir de documentos:

Si se llama a esto en varias ocasiones cuando el superficie no está listo (antes o después de Callback.surfaceCreated Callback.surfaceDestroyed), sus llamadas se estrangula a una velocidad lenta en para evitar consumir CPU.

¿Es posible que su bucle de extracción se inicie demasiado pronto para algunos dispositivos?Creo que este es el problema, ya que escribió:

Ahora he descubierto que si añado un retraso en el constructor de mi SurfaceView (de unos 10 segundos), la lentitud no se produce y todos funciona bien.

+0

Te doy +1 por encontrar eso en la documentación. También lo vi la semana pasada y lo probé y no solucionó el problema, aunque lo vuelva a leer, necesito verificar lo que hice. Voy a otorgar esto como la mejor respuesta de todos modos. – Kevin

0

Entonces, ¿tal vez podríamos usar holder.isCreating() para verificar el estado? este método devolverá verdadero si canvas todavía está creando.

Algo así como while (holder.isCreating()) {} can = holder.lockCanvas();

Pero estoy un poco confundido ahora. Como sé que se llama colbeck cuando se crea una vista de superficie. Deberíamos implementar la interfaz SurfaceHolder.Callback. Y cuando se crea la superficie, se llamará al método de devolución de llamada public void surfaceCreated (SurfaceHolder holder) {}. Desde el método surfaceCreated estoy comenzando el hilo gameloop.

0

he descubierto recientemente que si los grandes mapas de bits se utilizan para dibujar en el lienzo y estos mapas de bits se almacenan en la clase de actividad - los "_surfaceHolder.lockCanvas()" de comandos en sí dura mucho tiempo (alrededor de 70 ms en función del dispositivo) SIN EMBARGO, al mover el almacenamiento de mapas de bits a otra clase (en un archivo diferente, digamos MI_DATA), y la actividad tiene solo una referencia a esa nueva clase, resuelve el problema.

No tengo ninguna explicación para este fenómeno.

0

Me encontré con el mismo problema misterioso con Canvas drawing, pero lo resolvió cambiando Canvas drawing to drawing en el SurfaceView. Pero ahora tengo la llamada lockCanvas() constantemente lenta. Aquí están los resultados de mi observación. El problema es que sólo está presente en algunos dispositivos:

  • Galaxy Note 3 n900: tiene problemas
  • Galaxy Note 3 n9005: tiene problemas
  • Galaxy S4 i9505: tiene problemas
  • Galaxy Gio: No tiene problemas
  • LG G2 D802: tiene problemas
  • Galaxy S2 i9100: no hay problemas

que sustituyen temporalmente el SurfaceView extendiendo Ver e implementar onDraw(), y que tiene una mejor tasa de fotogramas

También me di cuenta, que los teléfonos Samsung usando GLES20Canvas en lugar de regular de Canvas con onDraw() dibujo, como una resultado, mejor rendimiento.

Cuestiones relacionadas