Google is committed to advancing racial equity for Black communities. See how.
Эта страница была переведа с помощью Cloud Translation API.
Switch to English

SurfaceView и GLSurfaceView

Android рамка приложения пользовательский интерфейс на основе иерархии объектов , которые начинаются с видом . Все элементы пользовательского интерфейса проходят серию измерений и процесс компоновки, который помещает их в прямоугольную область. Затем все видимые объекты представления визуализируются на поверхность, которая была настроена WindowManager, когда приложение было переведено на передний план. Поток пользовательского интерфейса приложения выполняет компоновку и рендеринг в буфер для каждого кадра.

SurfaceView

SurfaceView - это компонент, который можно использовать для встраивания дополнительного составного слоя в иерархию представлений. SurfaceView принимает те же параметры макета, что и другие представления, поэтому им можно управлять, как любым другим представлением, но содержимое SurfaceView прозрачно.

Когда вы выполняете рендеринг с использованием внешнего источника буфера, такого как контекст GL или медиа-декодер, вам необходимо скопировать буферы из источника буфера, чтобы отобразить буферы на экране. Использование SurfaceView позволяет вам это сделать.

Когда компонент представления SurfaceView собирается стать видимым, платформа просит SurfaceControl запросить новую поверхность у SurfaceFlinger. Чтобы получать обратные вызовы при создании или уничтожении поверхности, используйте интерфейс SurfaceHolder . По умолчанию вновь созданная поверхность размещается за поверхностью пользовательского интерфейса приложения. Вы можете переопределить Z-порядок по умолчанию, чтобы поместить новую поверхность поверх.

Рендеринг с помощью SurfaceView полезен в случаях, когда вам необходимо выполнить рендеринг на отдельной поверхности, например, когда вы выполняете рендеринг с помощью API камеры или контекста OpenGL ES. Когда вы выполняете рендеринг с помощью SurfaceView, SurfaceFlinger напрямую формирует буферы на экране. Без SurfaceView вам необходимо объединить буферы в заэкранную поверхность, которая затем будет объединена с экраном, поэтому рендеринг с помощью SurfaceView устраняет дополнительную работу. После рендеринга с помощью SurfaceView используйте поток пользовательского интерфейса для согласования с жизненным циклом действия и при необходимости внесите изменения в размер или положение представления. Затем Hardware Composer смешивает пользовательский интерфейс приложения и другие слои.

Новая поверхность является стороной производителя BufferQueue, потребителем которой является слой SurfaceFlinger. Вы можете обновить поверхность с помощью любого механизма, который может передавать BufferQueue, например, предоставляемых поверхностью функций Canvas, присоединения EGLSurface и рисования на поверхности с помощью GLES или настройки медиа-декодера для записи поверхности.

SurfaceView и жизненный цикл активности

При использовании SurfaceView визуализируйте поверхность из потока, отличного от основного потока пользовательского интерфейса.

Для действия с SurfaceView существует два отдельных, но взаимозависимых конечных автомата:

  • Приложение onCreate / onResume / onPause
  • Поверхность создана / изменена / уничтожена

Когда действие начинается, вы получаете обратные вызовы в следующем порядке:

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

Если вы нажмете назад, вы получите:

  1. onPause()
  2. surfaceDestroyed() ( surfaceDestroyed() непосредственно перед тем, как поверхность уйдет)

Если повернуть экран, действие будет разрушено и воссоздано заново, и вы получите полный цикл. Вы можете сказать, что это быстрый перезапуск, проверив isFinishing() . Можно запускать / останавливать действие так быстро, что surfaceCreated() выполняется после onPause() .

Если вы нажмете кнопку питания, чтобы onPause() экран, вы получите только onPause() без surfaceDestroyed() . Поверхность остается активной, и рендеринг можно продолжить. Вы можете продолжать получать события хореографа, если продолжите запрашивать их. Если у вас есть экран блокировки, который принудительно меняет ориентацию, ваша деятельность может быть перезапущена, когда устройство разблокировано. В противном случае вы можете выйти из пустого экрана с той же поверхностью, что и раньше.

Срок службы потока может быть привязан к поверхности или к активности, в зависимости от того, что вы хотите, чтобы произошло, когда экран погаснет. Поток может запускаться / останавливаться либо при запуске / остановке действия, либо при создании / уничтожении поверхности.

Наличие запуска / остановки потока при запуске / остановке активности хорошо работает с жизненным циклом приложения. Вы запускаете поток рендеринга в onResume() и останавливаете его в onStop() . При создании и настройке потока иногда поверхность уже существует, а иногда нет (например, она все еще активна после переключения экрана с помощью кнопки питания). Вы должны дождаться создания поверхности перед инициализацией в потоке. Вы не можете инициализировать обратный вызов surfaceCreate() потому что он не сработает снова, если поверхность не была воссоздана. Вместо этого запросите или кэшируйте состояние поверхности и отправьте его потоку рендеринга.

Наличие запуска / остановки потока на поверхности create / destroy работает хорошо, потому что поверхность и средство визуализации логически взаимосвязаны. Вы запускаете поток после создания поверхности, что позволяет избежать некоторых проблем с межпотоковой связью; а сообщения о создании / изменении поверхности просто пересылаются. Чтобы гарантировать, что рендеринг прекращается, когда экран становится пустым, и возобновляется, когда он очищается, скажите Choreographer прекратить вызывать обратный вызов отрисовки кадра. onResume() возобновляет обратные вызовы, если поток рендеринга запущен. Однако, если вы выполняете анимацию на основе времени, прошедшего между кадрами, может быть большой промежуток до прибытия следующего события; использование явного сообщения паузы / возобновления может решить эту проблему.

Оба варианта, независимо от того, привязан ли срок жизни потока к Activity или к поверхности, сосредоточены на том, как настроен поток средства визуализации и выполняется ли он. Связанная проблема заключается в извлечении состояния из потока, когда действие onStop() в onStop() или onSaveInstanceState() ); в таких случаях связывание продолжительности жизни потока с действием работает лучше всего, потому что после присоединения потока средства визуализации к состоянию визуализированного потока можно получить доступ без примитивов синхронизации.

GLSurfaceView

Класс GLSurfaceView предоставляет вспомогательные классы для управления контекстами EGL, межпотокового взаимодействия и взаимодействия с жизненным циклом активности. Вам не нужно использовать GLSurfaceView для использования GLES.

Например, GLSurfaceView создает поток для рендеринга и настраивает в нем контекст EGL. Состояние очищается автоматически, когда действие приостанавливается. Большинству приложений не нужно ничего знать об EGL, чтобы использовать GLES с GLSurfaceView.

В большинстве случаев GLSurfaceView может облегчить работу с GLES. В некоторых ситуациях это может мешать.