Google致力於提高黑人社區的種族平等。 怎麼看。
本頁面由 Cloud Translation API 翻譯而成。
Switch to English

SurfaceView和GLSurfaceView

Android應用程序框架UI基於以View開頭的對象層次結構。所有UI元素都經過一系列測量和佈局過程,以使其適合矩形區域。然後,將所有可見的視圖對象渲染到應用程序進入前景時由WindowManager設置的表面。應用程序的UI線程每幀執行佈局和渲染到緩衝區。

SurfaceView

SurfaceView是一個組件,可用於在視圖層次結構中嵌入其他復合層。 SurfaceView與其他視圖採用相同的佈局參數,因此可以像其他任何視圖一樣對其進行操作,但是SurfaceView的內容是透明的。

使用外部緩衝區源(例如GL上下文或媒體解碼器)進行渲染時,需要從緩衝區源複製緩衝區以在屏幕上顯示緩衝區。使用SurfaceView可以做到這一點。

當SurfaceView的視圖組件即將變得可見時,框架要求SurfaceControl從SurfaceFlinger請求新的表面。若要在創建或破壞曲面時接收回調,請使用SurfaceHolder接口。默認情況下,新創建的表面放置在應用程序UI表面的後面。您可以覆蓋默認的Z順序以將新曲面放在頂部。

在需要渲染到單獨的曲面的情況下(例如,使用Camera API或OpenGL ES上下文進行渲染時),使用SurfaceView渲染很有用。使用SurfaceView渲染時,SurfaceFlinger直接將緩衝區組成到屏幕上。如果沒有SurfaceView,則需要將緩衝區合成到屏幕上的表面,然後將其合成到屏幕上,因此使用SurfaceView進行渲染可以省去額外的工作。使用SurfaceView渲染後,使用UI線程與活動生命週期進行協調,並根據需要調整視圖的大小或位置。然後,硬件編輯器將應用程序UI和其他層混合在一起。

新表面是BufferQueue的生產者端,其消耗者是SurfaceFlinger層。您可以使用任何可提供BufferQueue的機制來更新表面,例如表面提供的Canvas函數,附加EGLSurface並使用GLES在表面上繪製,或配置媒體解碼器以寫入表面。

SurfaceView和活動生命週期

使用SurfaceView時,從主UI線程以外的線程渲染表面。

對於使用SurfaceView的活動,有兩個獨立但相互依賴的狀態機:

  • App onCreate / onResume / onPause
  • 創建/更改/銷毀表面

活動開始時,您將按以下順序獲得回調:

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

如果單擊返回,將得到:

  1. onPause()
  2. surfaceDestroyed() (在表面消失之前調用)

如果旋轉屏幕,則活動將被拆除並重新創建,您將獲得完整的周期。通過檢查isFinishing()可以知道它是快速重啟。可以如此快速地啟動/停止活動,以便在onPause()之後發生surfaceCreated() onPause()

如果點擊電源按鈕以使屏幕空白,則只會顯示onPause()而不會顯示surfaceDestroyed() 。曲面保持活動狀態,並且渲染可以繼續。如果繼續請求,您可以繼續獲取Choreographer事件。如果您使用鎖定屏幕強制改變方向,則取消設備空白時可能會重新啟動您的活動。否則,您可以像以前一樣從空白屏幕出來。

線程的壽命可以綁定到表面或活動,具體取決於屏幕變黑時要發生的情況。線程可以在“活動”啟動/停止或在曲面創建/銷毀時啟動/停止。

使線程在活動啟動/停止上啟動/停止與應用程序生命週期配合得很好。您可以在onResume()啟動渲染器線程,並在onStop()停止它。在創建和配置線程時,有時該表面已經存在,而有時則不存在(例如,使用電源按鈕切換屏幕後該表面仍然處於活動狀態)。在線程中初始化之前,您必須等待創建曲面。您無法在surfaceCreate()回調中進行初始化,因為如果未重新創建表面,它將不會再次觸發。而是查詢或緩存表面狀態,並將其轉發到渲染器線程。

使曲面上的線程開始/停止創建/銷毀效果很好,因為曲面和渲染器在邏輯上是交織在一起的。在創建表面之後,您可以啟動線程,這避免了一些線程間通信問題。和創建/更改表面的消息只是轉發。為確保渲染在屏幕變黑時停止並在其消除黑屏時恢復,請告訴Choreographer停止調用框架繪製回調。如果渲染器線程正在運行, onResume()將繼續執行回調。但是,如果根據幀之間經過的時間進行動畫處理,則下一個事件到達之前可能會有很大的間隔;使用顯式的暫停/繼續消息可以解決此問題。

線程的壽命是綁定到Activity還是曲面,這兩個選項都集中在渲染器線程的配置方式以及是否正在執行上。一個相關的問題是,當活動被殺死時(在onStop()onSaveInstanceState() ),從線程中提取狀態。在這種情況下,將線程的壽命與活動聯繫在一起是最有效的方法,因為在連接了渲染器線程之後,無需同步原語就可以訪問渲染線程的狀態。

GLSurfaceView

GLSurfaceView類提供了用於管理EGL上下文,線程間通信以及與活動生命週期交互的幫助程序類。您無需使用GLSurfaceView即可使用GLES。

例如,GLSurfaceView創建用於渲染的線程,並在那裡配置EGL上下文。活動暫停時,狀態會自動清除。大多數應用程序不需要任何有關EGL的知識就可以將GLES與GLSurfaceView結合使用。

在大多數情況下,GLSurfaceView可以簡化使用GLES的工作。在某些情況下,它可能會妨礙您。