Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

SurfaceView y GLSurfaceView

La interfaz de usuario del marco de aplicaciones de Android se basa en una jerarquía de objetos que comienzan con una vista . Todos los elementos de la interfaz de usuario pasan por una serie de medidas y un proceso de diseño que los encaja en un área rectangular. Luego, todos los objetos de vista visibles se renderizan en una superficie que fue configurada por WindowManager cuando la aplicación se puso en primer plano. El subproceso de la interfaz de usuario de la aplicación realiza el diseño y la representación en un búfer por fotograma.

SurfaceView

Un SurfaceView es un componente que puede usar para incrustar una capa compuesta adicional dentro de su jerarquía de vista. Un SurfaceView toma los mismos parámetros de diseño que otras vistas, por lo que se puede manipular como cualquier otra vista, pero el contenido de SurfaceView es transparente.

Cuando renderiza con una fuente de búfer externa, como el contexto GL o un decodificador de medios, necesita copiar búferes de la fuente de búfer para mostrar los búferes en la pantalla. El uso de SurfaceView le permite hacer eso.

Cuando el componente de vista de SurfaceView está a punto de volverse visible, el marco le pide a SurfaceControl que solicite una nueva superficie de SurfaceFlinger. Para recibir devoluciones de llamada cuando se crea o destruye la superficie, use la interfaz SurfaceHolder . De forma predeterminada, la superficie recién creada se coloca detrás de la superficie de la interfaz de usuario de la aplicación. Puede anular el orden Z predeterminado para colocar la nueva superficie en la parte superior.

El renderizado con SurfaceView es beneficioso en los casos en los que necesita renderizar en una superficie separada, como cuando renderiza con la API de cámara o un contexto OpenGL ES. Cuando renderiza con SurfaceView, SurfaceFlinger compone directamente búferes en la pantalla. Sin SurfaceView, necesita componer búferes en una superficie fuera de la pantalla, que luego se componen en la pantalla, por lo que la renderización con SurfaceView elimina el trabajo adicional. Después de renderizar con SurfaceView, use el subproceso de la interfaz de usuario para coordinar con el ciclo de vida de la actividad y realice ajustes en el tamaño o la posición de la vista si es necesario. Luego, Hardware Composer combina la interfaz de usuario de la aplicación y las otras capas.

La nueva superficie es el lado productor de una BufferQueue, cuyo consumidor es una capa SurfaceFlinger. Puede actualizar la superficie con cualquier mecanismo que pueda alimentar un BufferQueue, como las funciones Canvas suministradas por la superficie, adjuntar un EGLSurface y dibujar en la superficie con GLES, o configurar un decodificador de medios para escribir la superficie.

SurfaceView y el ciclo de vida de la actividad

Al usar SurfaceView, renderice la superficie desde un subproceso que no sea el subproceso principal de la IU.

Para una actividad con SurfaceView, hay dos máquinas de estado independientes pero interdependientes:

  • Aplicación onCreate / onResume / onPause
  • Superficie creada / cambiada / destruida

Cuando comienza la actividad, recibe devoluciones de llamada en este orden:

  1. onCreate()
  2. onResume()
  3. surfaceCreated()
  4. surfaceChanged()

Si hace clic en Atrás, obtiene:

  1. onPause()
  2. surfaceDestroyed() (llamado justo antes de que la superficie desaparezca)

Si gira la pantalla, la actividad se destruye y se recrea y obtiene el ciclo completo. Puede saber que es un reinicio rápido marcando isFinishing() . Es posible iniciar / detener una actividad tan rápido que surfaceCreated() ocurre después de onPause() .

Si toca el botón de encendido para dejar la pantalla en blanco, solo obtendrá onPause() sin surfaceDestroyed() . La superficie permanece activa y el renderizado puede continuar. Puede seguir recibiendo eventos de Choreographer si continúa solicitándolos. Si tiene una pantalla de bloqueo que fuerza una orientación diferente, su actividad puede reiniciarse cuando el dispositivo no esté en blanco. De lo contrario, puede salir de la pantalla en blanco con la misma superficie que antes.

La vida útil del hilo puede estar ligada a la superficie oa la actividad, dependiendo de lo que quieras que suceda cuando la pantalla se quede en blanco. El hilo puede iniciarse / detenerse en el inicio / detención de la actividad o en la creación / destrucción de la superficie.

Hacer que el hilo se inicie / se detenga al iniciar / detener la actividad funciona bien con el ciclo de vida de la aplicación. onResume() hilo del renderizador en onResume() y lo detiene en onStop() . Al crear y configurar el hilo, a veces la superficie ya existe, otras veces no (por ejemplo, todavía está activa después de alternar la pantalla con el botón de encendido). Debe esperar a que se cree la superficie antes de inicializar en el hilo. No puede inicializar en la devolución de llamada surfaceCreate() porque no se activará de nuevo si la superficie no se volvió a crear. En su lugar, consulte o almacene en caché el estado de la superficie y reenvíelo al subproceso del renderizador.

Hacer que el hilo comience / se detenga en la creación / destrucción de la superficie funciona bien porque la superficie y el renderizador están entrelazados lógicamente. El hilo se inicia después de que se crea la superficie, lo que evita algunos problemas de comunicación entre hilos; y los mensajes creados / modificados en la superficie simplemente se reenvían. Para asegurarse de que la representación se detenga cuando la pantalla se quede en blanco y se reanude cuando se abre, dígale a Choreographer que deje de invocar la devolución de llamada de extracción de fotogramas. onResume() reanuda las devoluciones de llamada si el subproceso del renderizador se está ejecutando. Sin embargo, si realiza la animación basándose en el tiempo transcurrido entre fotogramas, podría haber un gran intervalo antes de que llegue el próximo evento; El uso de un mensaje explícito de pausa / reanudación puede resolver este problema.

Ambas opciones, ya sea que la vida útil del subproceso esté vinculada a la Actividad o la superficie, se centran en cómo se configura el subproceso del renderizador y si se está ejecutando. Una preocupación relacionada es extraer el estado del hilo cuando se mata la actividad (en onStop() o onSaveInstanceState() ); en tales casos, vincular la vida útil del subproceso a la actividad funciona mejor porque una vez que se ha unido el subproceso del renderizador, se puede acceder al estado del subproceso renderizado sin primitivas de sincronización.

GLSurfaceView

La clase GLSurfaceView proporciona clases auxiliares para administrar contextos EGL, comunicación entre subprocesos e interacción con el ciclo de vida de la actividad. No es necesario utilizar GLSurfaceView para utilizar GLES.

Por ejemplo, GLSurfaceView crea un hilo para renderizar y configura un contexto EGL allí. El estado se limpia automáticamente cuando la actividad se detiene. La mayoría de las aplicaciones no necesitan saber nada sobre EGL para usar GLES con GLSurfaceView.

En la mayoría de los casos, GLSurfaceView puede facilitar el trabajo con GLES. En algunas situaciones, puede interferir.