Android中View, SurfaceView的繪圖和GLSurfaceView繪圖有區別嗎?

在做一個功能的時候一開始用的View繪圖,在有些性能一般的機器上會比較卡,後來使用SurfaceView來繪圖,性能提高了很多,但是在非常垃圾的機器上還是會卡。後來本來打算嘗試用GLSurfaceView繪圖。但是因為OpenGL ES的API不太會用就一直沒實現出來,然後就擱置了。

但是我有一個疑問,就是,如果我用GLSurfaceView的API封裝一套和Canvas一樣的介面,繪圖上,GLSurfaceView會更加快速么?


  • View:顯示視圖,內置畫布,提供圖形繪製函數、觸屏事件、按鍵事件函數等;必須在UI主線程內更新畫面,速度較慢
  • SurfaceView:基於view視圖進行拓展的視圖類,更適合2D遊戲的開發;是view的子類,類似使用雙緩機制,在新的線程中更新畫面所以刷新界面速度比view快。
  • GLSurfaceView:基於SurfaceView視圖再次進行拓展的視圖類,專用於3D遊戲開發的視圖;是SurfaceView的子類,openGL專用。

在2D遊戲開發中,大致可以分為兩種遊戲框架,View和SurfaceView。 View和SurfaceView區別:

  • View:必須在UI的主線程中更新畫面,用於被動更新畫面。

  • surfaceView:UI線程和子線程中都可以。在一個新啟動的線程中重新繪製畫面,主動更新畫面。

UI的主線程中更新畫面 可能會引發問題,比如你更新畫面的時間過長,那麼你的主UI線程會被你正在畫的函數阻塞。那麼將無法響應按鍵,觸屏等消息。當使用surfaceView 由於是在新的線程中更新畫面所以不會阻塞你的UI主線程。但這也帶來了另外一個問題,就是事件同步,涉及到線程同步。所以基於以上,根據遊戲特點,一般分成兩類。

  • 1 被動更新畫面的。比如棋類,這種用view就好了。因為畫面的更新是依賴於 onTouch 來更新,可以直接使用 invalidate。 因為這種情況下,這一次Touch和下一次的Touch需要的時間比較長些,不會產生影響。
  • 2 主動更新。比如一個人在一直跑動。這就需要一個單獨的thread不停的重繪人的狀態,避免阻塞main UI thread。所以顯然view不合適,需要surfaceView來控制。


感謝評論中各位大牛的糾正~~

個人理解:

1)使用canvas/paint方式的繪圖為軟體渲染,通過cpu實現;使用opengles/shader方式的繪圖為硬體加速渲染,通過gpu實現。

2)surfaceview和glsurfaceview的顯示一般結合opengles,使用紋理(texture),為硬體渲染,通過gpu實現

3)glsurfaceview是surfaceview的子類,在後者基礎上封裝了egl環境管理,以及render線程

4)opengles繪製函數及shader是平台無關的,需要egl環境對接android/ios等平台

5)android graphic 底層都與BufferQueue、Surfaceflinger等相關,具體可參考android開發者文檔

個人經驗,如有不對之處請幫忙指出


surfaceview是view的子類,GLSurfaceView是surfaceview的子類。毫無疑問子類會比父類功能更強大。但是樓主所問的

用GLSurfaceView的API封裝一套和Canvas一樣的介面,繪圖上,GLSurfaceView會更加快速么?

那還真不一定。原因在於android系統內部其實對view做了許多優化,比如說 硬體加速。而硬體加速的本質,其實就是將所有的繪製命令 放入一個列表DisplayList,然後用 OpenGL ES的繪製指令 去做最終繪製。所以,你想做的 ,android已經替你做好了。但是有些低端機型上不支持硬體加速,才導致繪製效率低下。這些不支持硬體加速的 機型往往也可能無法完全支持OpenGL ES。

而且換個角度來說,OpenGL的效率之所以高一部分是因為 非同步線程進行繪製能獲得更平滑的繪製效果;另一部分是因為分層操作,它在你繪製上一幅畫面的時候就提前繪製好下一副畫面,然後再在顯示下一副圖片的時候直接交換,不同於像view那樣通過刷新臟區域重新繪製。但這就意味著要消耗雙倍的內存。 低端機的內存是否足夠支撐OpenGL的消耗也是個需要考慮的問題。

另外GLSurfaceView還有一個特點,就是它不支持控制項動畫。原因在於 OpenGL是一套跨平台的圖形庫,為了跨平台,它裡面不包含任何執行窗口任務或者處理用戶輸入的函數,我們需要通過應用程序本身所運行的窗口系統來提供相應操作才能處理這些操作,所以OpenGL的繪製相當於是在view上打了一個洞直接繪製在surface上。如果你想要做一個層級比較深的界面,直接用surfaceview會比用OpenGL方便的多。

當然,作為最底層的圖形庫,OpenGL的性能是毋庸置疑的。像素級的控制,通過著色器能達到很多view 難以達到的效果。具體選擇用哪種方式,還是要視情況而定。


我覺得……題主你是指動畫吧?

view只能在主線程繪製,surfaceview則是可以多線程刷新,而opengl則是更深一層的基於native動畫庫,做了大量優化和封裝。同樣的手機上同樣的動畫,view只能跑4幀的,opengl實現能輕鬆24幀,這就是差距。

當然運行成本和實現成本往往不可兼得就是了


Android opensource上面專門有講。翻牆上去看。


推薦閱讀:

過度依賴框架有什麼不好?
Android 開發有什麼好的架構么?
Android 應用的真正入口是哪裡?
有哪些大齡非 CS 科班出身的青年轉行程序員,結果失敗的例子?

TAG:Android開發 | Android | 計算機圖形學和可視化 |