欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android SurfaceView與TextureView使用方法詳細講解

 更新時間:2022年10月31日 17:00:48   作者:幸大叔  
SurfaceView和TextureView都繼承View,與普通的View不同的是,它倆可以在獨立線程中繪制渲染,性能更高,所以常被應(yīng)用在對繪制速率要求比較高的場景,比如相機預(yù)覽,視頻播放等等

Surface

官方對Surface的解釋是:由屏幕合成器管理的原始緩沖區(qū)上的句柄,所謂原生緩沖器,是用于保存當前窗口的像素數(shù)據(jù)的,也就是說,通過Surface可以獲取原生緩沖器以及其中的內(nèi)容。Surface對應(yīng)一塊屏幕緩沖區(qū),每個Window對應(yīng)一個Surface,任何View都畫在Surface上,Surface中的Canvas,是用于提供畫圖的地方。

SurfaceView

SurfaceView與普通的View不同,它擁有自己的Surface,它的工作方式是創(chuàng)建一個區(qū)別于應(yīng)用窗口的新窗口,與宿主窗口分離,可以在單獨線程中處理業(yè)務(wù),不受View的屬性控制,無法進行平移縮放等轉(zhuǎn)換,它是通過“雙緩沖”機制來達到高效的界面刷新效果。

雙緩沖技術(shù)是把要處理的圖片在內(nèi)存中處理好之后,再將其顯示在屏幕上。雙緩沖主要是為了解決反復局部刷屏帶來的閃爍。把要畫的東西先畫到一個內(nèi)存區(qū)域里,然后整體的一次性畫出來。

下面通過一個相機預(yù)覽的功能,來看一下SurfaceView的具體使用

private lateinit var surfaceHolder: SurfaceHolder

獲取攝像機管理類,打開某個具體的攝像機,在打開成功的回調(diào)里面,創(chuàng)建預(yù)覽請求

        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
                ) {
                    //無相機權(quán)限
                    return
                }
                try {
                    //獲取可用相機設(shè)備列表
                    val cameraIdList = cameraManager.cameraIdList
                    //打開相機
                    cameraManager.openCamera(
                        cameraIdList[0],
                        //攝像頭創(chuàng)建監(jiān)聽
                        object : CameraDevice.StateCallback() {
                            override fun onOpened(p0: CameraDevice) { //打開攝像頭
                                try {
                                    startPreview(p0)
                                } catch (e: CameraAccessException) {
                                    e.printStackTrace()
                                }
                            }
                            override fun onDisconnected(p0: CameraDevice) { //關(guān)閉攝像頭
                                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")
            }
        })

開始預(yù)覽

    private fun startPreview(cameraDevice: CameraDevice) {
        val captureRequest = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
        captureRequest.addTarget(surfaceHolder.surface)
        cameraDevice.createCaptureSession(
            listOf(surfaceHolder.surface),
            //會話狀態(tài)回調(diào)
            object : CameraCaptureSession.StateCallback() {
                override fun onConfigured(p0: CameraCaptureSession) {
                    try {
                        // 創(chuàng)建預(yù)覽需要的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
        )
    }

這樣,簡易的相機預(yù)覽功能就出來啦,當然,我們還需要申請CAMERA權(quán)限,這里略去。

TextureView

TextureView可以說是一個結(jié)合了View和SurfaceTexture的View對象,一個可以把內(nèi)容流作為外部紋理輸出在上面的 View,它只能用于開啟了硬件加速的窗口,TextureView不會創(chuàng)建一個獨立的窗口,而是像普通的View一樣,可以進行平移、旋轉(zhuǎn)等動畫,TextureView在Andriod 4.0之后的 API 中才能使用,不過現(xiàn)在的安卓設(shè)備基本不存在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不同的是,它對圖像流的處理并不直接顯示,而是轉(zhuǎn)為GL外部紋理,因此可用于圖像流數(shù)據(jù)的二次處理,如Camera濾鏡,桌面特效等,但是這樣會有若干幀的延遲。同時,由于它本身管理BufferQueue,因此內(nèi)存消耗也會稍微大一些。比如Camera的預(yù)覽數(shù)據(jù),變成紋理后就可以通過SurfaceTexture交給TextureView作為View層級中的一個硬件加速層來顯示。

SurfaceView和TextureView的區(qū)別

  • SurfaceView是直接輸出的,擁有自己獨立Surface,它的渲染可以放在單獨線程,其缺點是不能做變形和動畫。
  • TextureView是一個可以把內(nèi)容流作為外部紋理輸出的,本身必須是一個硬件加速層,顯示畫面更新時有1~3幀的延遲。
  • TextureView本身也包含了SurfaceTexture,它與SurfaceView+SurfaceTexture組合相比,也可以把內(nèi)容流上的圖像轉(zhuǎn)成紋理輸出,區(qū)別在于TextureView是在View層級中繪制的,而SurfaceView+SurfaceTexture在單獨的Surface上做繪制的。
SurfaceViewTextureView
占用內(nèi)存低占用內(nèi)存高
耗電低耗電高
繪制及時1-3幀延時
不支持動畫截圖支持動畫截圖

個人覺得,對于需要不斷更新畫布的游戲來說,SurfaceView是最好的選擇,對于視頻播放器或相機應(yīng)用的開發(fā),則TextureView更加適合。

到此這篇關(guān)于Android SurfaceView與TextureView使用方法詳細講解的文章就介紹到這了,更多相關(guān)Android SurfaceView與TextureView內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論