首頁 > 軟體

Android音訊開發之SurfaceView的使用詳解

2022-04-14 10:02:08

SurfaceView

SurfaceView從原始碼上看繼承自View,但在內部實現上SurfaceView和其他View有很多區別。 SurfaceView主要作用是提供一個直接繪圖表面嵌入到檢視結構中,實際上真正做繪製能力的是Surface。因此SurfaceView和宿主視窗是分離的。正常情況下視窗的View共用同一個Window,而Window也對應一個Surface,所有View也就共用同一個Surface。所以SurfaceView具備獨立的Surface,相當於和宿主視窗繪製是分離互不干擾。

不同點

不同點SurfaceViewView
繪製結構在View當中,但繪製表面是獨立的。內部擁有自己的Canvas進行繪製操作和宿主視窗共用同一個繪圖表面
重新整理視窗重新整理不需要重繪宿主視窗任何一個子元素或是區域性重新整理都會使得整個檢視結構發生重繪
執行緒執行緒獨立,不影響主執行緒 使用介面頻繁重新整理在UI主執行緒使用
操作低版本不支援平移、縮放、旋轉等動畫 不具備View屬性控制均可正常操作
重新整理可控制重新整理頻率、雙快取機制只在主執行緒重新整理更新

雙緩衝機制

SurfaceView將視訊流解析成一幀幀影象資料顯示。例如一幀影象顯示後,等待下一幀影象可能存在還未及時解析的情況,這種情況下就會導致畫面不流暢。利用雙緩衝可以避免這種情況,可以理解雙緩衝是兩個執行緒輪流解析視訊流影象資料兩者交替進行解析和渲染操作從而保證視訊流能夠流暢播放。

SurfaceHolder

SurfaceView雙緩衝機制事實上是比較消耗系統記憶體。因此當SurfaceView在不可見狀態下就會去銷燬SurfaceHolder來減輕記憶體開銷。因此就有了SurfaceHolderaddCallback方法來監聽SurfaceHolder狀態。

  • void surfaceCreated(@NonNull SurfaceHolder holder); 建立回撥
  • void surfaceChanged(@NonNull SurfaceHolder holder, @PixelFormat.Format int format, @IntRange(from = 0) int width, @IntRange(from = 0) int height); 修改回撥
  • void surfaceDestroyed(@NonNull SurfaceHolder holder); 銷燬回撥

使用

自定義繼承SurfaceView可以自定義繪製內容。當建立SurfaceHolder成功後再surfaceCreated回撥中呼叫lockCanvas獲取到SurfaceHolder的畫布並鎖定,然後繪製內容。繪製結束後呼叫unlockCanvasAndPost釋放並提交畫布改動資訊,讓新資料在畫布上進行展示。

public class SurfaceViewTest extends SurfaceView implements SurfaceHolder.Callback{
    private SurfaceHolder mSurfaceHolder;
    private Canvas mCanvas;
    private Paint paint;

    public SurfaceViewTest(Context context) {
        this(context,null,0);
    }

    public SurfaceViewTest(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public SurfaceViewTest(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mSurfaceHolder = getHolder(); // 初始化
        mSurfaceHolder.addCallback(this);
        setFocusable(true);
        setFocusableInTouchMode(true);
        this.setKeepScreenOn(true);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.RED);
        paint.setStrokeWidth(5);
        paint.setStyle(Paint.Style.STROKE);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // 建立成功後就能通過執行緒繪製自定義內容
        new Thread(new Runnable() {
            @Override
            public void run() {
                draw();
            }
        }).start();
    }
    private void draw() {
        try {
            mCanvas = mSurfaceHolder.lockCanvas();
            mCanvas.drawCircle(500,500,300,paint);
            mCanvas.drawCircle(100,100,20,paint);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (mCanvas != null)
                mSurfaceHolder.unlockCanvasAndPost(mCanvas);
        }
    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {}
}

以上就是Android音訊開發之SurfaceView的使用詳解的詳細內容,更多關於Android SurfaceView的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com