談談對SurfaceView的理解

初識SurfaceView

剛開始做android app開發(fā)的時候,我覺得在app上展示播放一段視頻,是一件很高大上的事情,后來研究了一下,原來,這都要歸功于SurfaceView這個東東。

Surface + View

怎么理解SurfaceView呢?顧名思義就是Surface+View了,因此,這個東西有兩重身份:首先,是一個View;其次還是一個帶有Surface的View。首先聊聊View,View我們可以理解為視圖了,android上的imageview,textview之類的,都可以理解為視圖,這些視圖可以直接在layout上規(guī)劃。所以,SurfaceView,類似的,也可以直接在xml上規(guī)劃。再來聊聊Surface,Surface可以理解為一塊畫布,應用可以在Surface上繪制自己的圖像。對于視頻而言,其本質,也是圖像,只不過是在不斷變化的圖像,確切的說,是每秒變化30幀的圖像(30fps)。
總結起來,SurfaceView本身是一個視圖,可以在layout中布局,在這個視圖中有一個畫布是Surface,我們可以將圖片繪制在這個Surface上。

類圖

下面用類圖介紹一下SurfaceView的大致框架


SurfaceView.png

這個類圖以camera預覽為場景,介紹SurfaceView,從類圖中可以看出,SurfaceView繼承自(is-a)View,另外,SurfaceView中有一個SurfaceHolder,可以通過getHolder得到這個holder,這個holder有一個方法addCallback,可以向這個類中注冊一個Callback,并且SurfaceHolder中有一個(has-a)Surface。Camera中通過setPreviewDisplay像Camera注冊一個SurfaceHolder,這樣底層的Camera就可以將圖像渲染在SurfaceHolder的Surface中,最后SurfaceFlinger會將所有應用的Surface進行混合,我們在手機看到的,就是最終混合的效果。

課題討論

為什么要有SurfaceHolder.Callback ?

既然SurfaceView具有雙重身份,我們直接在Surface上繪制不就可以了?為何需要注冊一個SurfaceHolder.Callback回調呢?我覺得初識SurfaceView的同學,可能也會被這個回調嚇到,想想Android中有那么多視圖,TextView,ImageView等等,都不需要注冊類似的回調函數,為何SurfaceView如此特殊?我的理解是,SurfaceView固然存在雙重身份,但我們在xml中注冊后,僅僅可以保證這個View已經初始化好了,但是Surface可未必已經初始化好了,如果此時就在View中直接注冊的話,有可能系統(tǒng)就會崩潰吧。那我們如何知道這個Surface確實已經創(chuàng)建成功了?這就有兩種方式:同步的方式和異步的方式。同步的方式就是一直等待Surface的初始化,Surface初始化好后再往下進行,在這個過程中,系統(tǒng)一直處于阻塞狀態(tài);另一種方式就是異步方式,也就是注冊一個回調函數,當Surface創(chuàng)建好后,通過這個監(jiān)聽的函數,告知上層應用?;貞浺幌翸ediaPlayer就有類似的兩種方式。在這里,SurfaceView采用的是第二種方式,我覺得主要原因可能是由于SurfaceView本身是在主線程中創(chuàng)建的,我們總不能讓主線程阻塞吧!既然是異步方式,當然就需要注冊監(jiān)聽函數了,這也就是SurfaceHolder.Callback的作用了。因此,我們需要向底層注冊一個回調函數,在SurfaceView創(chuàng)建時或者改變時或者銷毀時,告訴我們一下,我們好做相應的處理。

SurfaceHolder的作用

既然SurfaceView就是Surface+View,那為何要設計SurfaceHolder呢?我想可以這樣理解,Surface只不過是SurfaceHolder的其中一個側面,確切的說,可以理解為畫布,而很多其他的側面,比如和外部打交道等,都由SurfaceHolder來管理就可以了,這樣Surface可以專心致志的干他需要干的事情。實際上在Android中有很多類似的模塊,都采用這種類似的模式,比如XXXManager,XXXMaster等等,都采用了類似的處理方式。因此,對于外部而言,也不必知道Surface的存在,他們只要拿到SurfaceHolder就足夠了,比如在Camera預覽時,在setPreviewDisplay時,將SurfaceHolder傳入就可以了。特別的,在SurfaceHolder.Callback的三個回調函數中,都會以參數的形式將SurfaceHolder傳回,這樣我們可以更方便的使用這個holder。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容