網站首頁 編程語言 正文
Surface
官方對Surface的解釋是:由屏幕合成器管理的原始緩沖區上的句柄,所謂原生緩沖器,是用于保存當前窗口的像素數據的,也就是說,通過Surface可以獲取原生緩沖器以及其中的內容。Surface對應一塊屏幕緩沖區,每個Window對應一個Surface,任何View都畫在Surface上,Surface中的Canvas,是用于提供畫圖的地方。
SurfaceView
SurfaceView與普通的View不同,它擁有自己的Surface,它的工作方式是創建一個區別于應用窗口的新窗口,與宿主窗口分離,可以在單獨線程中處理業務,不受View的屬性控制,無法進行平移縮放等轉換,它是通過“雙緩沖”機制來達到高效的界面刷新效果。
雙緩沖技術是把要處理的圖片在內存中處理好之后,再將其顯示在屏幕上。雙緩沖主要是為了解決反復局部刷屏帶來的閃爍。把要畫的東西先畫到一個內存區域里,然后整體的一次性畫出來。
下面通過一個相機預覽的功能,來看一下SurfaceView的具體使用
private lateinit var surfaceHolder: SurfaceHolder
獲取攝像機管理類,打開某個具體的攝像機,在打開成功的回調里面,創建預覽請求
val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
val surfaceView = findViewById<SurfaceView>(R.id.surfaceView)
surfaceHolder = surfaceView.holder
surfaceHolder.setKeepScreenOn(true)
surfaceHolder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(p0: SurfaceHolder) {
if (ActivityCompat.checkSelfPermission(
this@SurfaceActivity,
Manifest.permission.CAMERA
) != PackageManager.PERMISSION_GRANTED
) {
//無相機權限
return
}
try {
//獲取可用相機設備列表
val cameraIdList = cameraManager.cameraIdList
//打開相機
cameraManager.openCamera(
cameraIdList[0],
//攝像頭創建監聽
object : CameraDevice.StateCallback() {
override fun onOpened(p0: CameraDevice) { //打開攝像頭
try {
startPreview(p0)
} catch (e: CameraAccessException) {
e.printStackTrace()
}
}
override fun onDisconnected(p0: CameraDevice) { //關閉攝像頭
p0.close()
}
override fun onError(p0: CameraDevice, p1: Int) {
Log.i(tag, "CameraDevice.StateCallback onError")
}
},
null
)
} catch (e: CameraAccessException) {
e.printStackTrace()
}
}
override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) {
Log.i(tag, "surfaceChanged")
}
override fun surfaceDestroyed(p0: SurfaceHolder) {
Log.i(tag, "surfaceDestroyed")
}
})
開始預覽
private fun startPreview(cameraDevice: CameraDevice) {
val captureRequest = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
captureRequest.addTarget(surfaceHolder.surface)
cameraDevice.createCaptureSession(
listOf(surfaceHolder.surface),
//會話狀態回調
object : CameraCaptureSession.StateCallback() {
override fun onConfigured(p0: CameraCaptureSession) {
try {
// 創建預覽需要的CaptureRequest.Builder
val previewRequestBuilder =
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
previewRequestBuilder.addTarget(surfaceHolder.surface)
val previewRequest = previewRequestBuilder.build()
p0.setRepeatingRequest(previewRequest, null, null)
} catch (e: CameraAccessException) {
e.printStackTrace()
}
}
override fun onConfigureFailed(p0: CameraCaptureSession) {
Log.i(tag, "onConfigureFailed")
}
}, null
)
}
這樣,簡易的相機預覽功能就出來啦,當然,我們還需要申請CAMERA權限,這里略去。
TextureView
TextureView可以說是一個結合了View和SurfaceTexture的View對象,一個可以把內容流作為外部紋理輸出在上面的 View,它只能用于開啟了硬件加速的窗口,TextureView不會創建一個獨立的窗口,而是像普通的View一樣,可以進行平移、旋轉等動畫,TextureView在Andriod 4.0之后的 API 中才能使用,不過現在的安卓設備基本不存在Andriod 4.0之前的版本了,所以這點不必在意。
TextureView的使用也比較簡單,需要獲取到它的SurfaceTexture,然后就可以以此來渲染了,下面通過一個簡易的視頻播放的示例,來瞧瞧它是怎么使用的。
val textureView = findViewById<TextureView>(R.id.textureView)
val mediaPlayer = MediaPlayer()
textureView.surfaceTextureListener = object : TextureView.SurfaceTextureListener {
override fun onSurfaceTextureAvailable(p0: SurfaceTexture, p1: Int, p2: Int) {
with(mediaPlayer) {
setDataSource(GlobalData.videoUrl)
setSurface(Surface(p0))
prepare()
start()
Log.i(tag, "setOnPreparedListener")
setOnPreparedListener {
it.start()
}
}
}
override fun onSurfaceTextureSizeChanged(p0: SurfaceTexture, p1: Int, p2: Int) {
}
override fun onSurfaceTextureDestroyed(p0: SurfaceTexture): Boolean {
mediaPlayer.stop()
mediaPlayer.release()
return true
}
override fun onSurfaceTextureUpdated(p0: SurfaceTexture) {
}
}
SurfaceTexture
SurfaceTexture是Surface和OpenGL ES紋理的組合,用于提供輸出到OpenGL ES紋理的Surface,和SurfaceView不同的是,它對圖像流的處理并不直接顯示,而是轉為GL外部紋理,因此可用于圖像流數據的二次處理,如Camera濾鏡,桌面特效等,但是這樣會有若干幀的延遲。同時,由于它本身管理BufferQueue,因此內存消耗也會稍微大一些。比如Camera的預覽數據,變成紋理后就可以通過SurfaceTexture交給TextureView作為View層級中的一個硬件加速層來顯示。
SurfaceView和TextureView的區別
- SurfaceView是直接輸出的,擁有自己獨立Surface,它的渲染可以放在單獨線程,其缺點是不能做變形和動畫。
- TextureView是一個可以把內容流作為外部紋理輸出的,本身必須是一個硬件加速層,顯示畫面更新時有1~3幀的延遲。
- TextureView本身也包含了SurfaceTexture,它與SurfaceView+SurfaceTexture組合相比,也可以把內容流上的圖像轉成紋理輸出,區別在于TextureView是在View層級中繪制的,而SurfaceView+SurfaceTexture在單獨的Surface上做繪制的。
SurfaceView | TextureView |
---|---|
占用內存低 | 占用內存高 |
耗電低 | 耗電高 |
繪制及時 | 1-3幀延時 |
不支持動畫截圖 | 支持動畫截圖 |
個人覺得,對于需要不斷更新畫布的游戲來說,SurfaceView是最好的選擇,對于視頻播放器或相機應用的開發,則TextureView更加適合。
原文鏈接:https://blog.csdn.net/qq_45485851/article/details/126367125
相關推薦
- 2022-07-03 關于python中range()的參數問題_python
- 2022-07-03 pandas創建series的三種方法小結_python
- 2022-04-19 教你如何從正在運行的容器創建?Docker?映像_docker
- 2022-09-06 Python利用contextvars實現管理上下文變量_python
- 2023-05-08 Python實現統計文章閱讀量的方法詳解_python
- 2022-06-17 mongodb?數據塊的遷移流程分析_MongoDB
- 2022-07-10 網絡I/o編程模型23 netty的出站與入站中handler加載與執行順序
- 2022-03-19 CentOS7下安裝MongoDB數據庫過程_MongoDB
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支