在一般的Android程序中,UI都是在主線程處理,但是,有些可能比較復(fù)雜的動(dòng)畫(huà)會(huì)卡頓主線程,如相機(jī),為了解決這個(gè)問(wèn)題,Android提供了SurfaceView,即在非主線程繪制UI。
SurfaceView在android.view包下,從Android1.0開(kāi)始支持。
public class MySurface extends SurfaceView implements Runnable{}
從中可以看出,我們?cè)谑褂?code>SurfaceView時(shí),一般是自定義一個(gè)類,并繼承SurfaceView
和Runnable
,熟悉Java的應(yīng)該能知道,Runnable
是實(shí)現(xiàn)多線程的接口,由此可見(jiàn),我們定義的MySurface
有多線程的特征。
那SurfaceView
又是什么呢?
從官方文檔看,SurfaceView
繼承自android.view.View,也就是說(shuō),SurfaceView
也是和ImageView
,TextView
類似的一個(gè)普通的View。
然后再看看官方對(duì)SurfaceView
的介紹:
第一句提供一個(gè)嵌入在View樹(shù),專用于繪制Surface
,View樹(shù)我想大家都知道類似如下,可以用Android Tool:View Hierarchy查看
那什么是Surface呢?
從中可以看到,
Surface
繼承自Object
而不是View
,且實(shí)現(xiàn)了Parcelable
,可見(jiàn)Surface
不是一個(gè)傳統(tǒng)意義上的View
。再看看官方介紹
介紹很簡(jiǎn)短的一句話:由屏幕顯示內(nèi)容合成器(screen compositor)所管理的原始緩沖區(qū)的句柄,從中可以看到,
Surface
是個(gè)句柄,通過(guò)這個(gè)句柄,可以獲得原始緩沖區(qū)及其內(nèi)容,原始緩沖區(qū)用于保存當(dāng)前窗口的像素?cái)?shù)據(jù)。
從Surface
的公開(kāi)方法中,可以看到有一個(gè)lockCanvas
方法,傳入一個(gè)矩形區(qū)域,返回一個(gè)Canvas
。
Canvas
大家應(yīng)該很熟悉,從字面直譯是畫(huà)布的意思,也就是說(shuō),你可以在Canvas
這塊畫(huà)布上繪制你想要的圖像,實(shí)際上也是這個(gè)用途
看一下
lockCanvas
的介紹
從Surface
獲取一塊畫(huà)布用于繪制,在繪制結(jié)束后,調(diào)用者必須執(zhí)行unlockCanvasAndPost(Canvas)
來(lái)將新繪制的內(nèi)容發(fā)送到Surface
。
再看看參數(shù)inOutDirty
:調(diào)用者想要重新繪制的一塊廢棄區(qū)域,這個(gè)方法可以被用于擴(kuò)展dirty區(qū)域,比如像縮放Surface
,調(diào)用者也可以傳遞null
,如果是這樣的話,整個(gè)Surface
應(yīng)該被重新繪制。
而unlockCanvasAndPost(Canvas)
這個(gè)方法則是將Canvas
中繪制的內(nèi)容發(fā)送給Surface
。
由此可見(jiàn),雖然Surface
沒(méi)有繼承自View
,但是它擁有一塊可繪制區(qū)域用于繪制內(nèi)容,但是因?yàn)樗鼪](méi)有繼承自View
,所以不能直接用于View
樹(shù)。
說(shuō)到這里,應(yīng)該能明白SurfaceView
是什么了吧,接著看SurfaceView
官方文檔:
You can control the format of this surface and, if you like, its size; the SurfaceView takes care of placing the surface at the correct location on the screen
:“你可以控制Surface
的格式,甚至尺寸,和位置”,從這里可以看出,SurfaceView存在的意義就是將不可以插入View hierarchy的Surface
轉(zhuǎn)為可以插入的SurfaceView
。
The surface is Z ordered so that it is behind the window holding its SurfaceView; the SurfaceView punches a hole in its window to allow its surface to be displayed. The view hierarchy will take care of correctly compositing with the Surface any siblings of the SurfaceView that would normally appear on top of it. This can be used to place overlays such as buttons on top of the Surface, though note however that it can have an impact on performance since a full alpha-blended composite will be performed each time the Surface changes.
Surface
是在Z軸的,所以它應(yīng)該在SurfaceView
的底部,SurfaceView
在自己身上打了個(gè)洞以便讓Surface
能被看到,View hierarchy會(huì)正確的顯示Surface
的位置,其他的View
也可以出現(xiàn)在它的上方,這可以用于將一個(gè)按鈕放置在Surface
的上方,需要注意的是,將一個(gè)透明的按鈕放置在Surface
的上方,每次Surface
的變化都會(huì)導(dǎo)致按鈕的重新繪制。
再看看這句Access to the underlying surface is provided via the SurfaceHolder interface, which can be retrieved by calling getHolder()
“需要訪問(wèn)底層的Surface
,你可以通過(guò)提供的SurfaceHolder
來(lái)訪問(wèn),SurfaceHolder
可以通過(guò)getHolder()
得到”。
The Surface will be created for you while the SurfaceView's window is visible; you should implement surfaceCreated(SurfaceHolder) and surfaceDestoryed(SurfaceHolder) to discover when the Surface is created and destroyed as the window is shown and hidden.
只有SurfaceView
可見(jiàn)是,Surface
才會(huì)被創(chuàng)建,你可以繼承surfaceCreated
和surfaceDestoryed
獲得。
到此,SurfaceView
是什么應(yīng)該能明白了吧。