オーディオとビデオの開発シリーズ (4) - Android Surfaceview の包括的な理解

SurfaceView と通常の View の違いは何ですか?

SurfaceView と通常の View では、実装原理や使用シーンが大きく異なります。

オーディオとビデオの詳細については、公式アカウントに注意してください: 攻撃のコード ホーム

実装原理
SurfaceView は、実際には非 UI スレッドで独立して描画操作を実行できる Surface を含む View であり、より高い描画効率を実現できます。通常の View は UI スレッドで描画されるため、描画処理が複雑すぎると UI がフリーズする原因になります。

使用シナリオ
通常のビューは、TextView、ボタン、およびその他のコントロールなどの静的な UI 表示に適しています。動画再生やゲーム開発など、リアルタイムレンダリングが必要なシーンに適しています。SurfaceView はより高い描画効率を実現できるため、これらのアプリケーションを実装する場合、SurfaceView を使用するとより優れたユーザー エクスペリエンスを提供できます。

サーフェス ビューの機能:

1) メイン スレッド リソースの占有による UI のフリーズを回避するために、非 UI スレッドで描画操作を実行できます; 2
) 基盤となる Surface オブジェクトの直接操作をサポートし、より複雑で効率的な描画操作を
可能にします; 3) 透明な背景をサポートします。よりリッチな UI 効果を実現;
4) 画面のちらつきやティアリングを回避できるダブル バッファリング メカニズムをサポートします。

なお、SurfaceView の描画操作はサブスレッドで行うため、UI の対話操作を行う場合は、スレッド間通信に Handler などのスレッド通信方式を使用する必要があります。

SurfaceView API の紹介

1.SurfaceHolder
SurfaceHolderはSurfaceViewの内部クラスで、SurfaceViewのSurfaceオブジェクトを取得し、Surfaceの操作方法を提供します。通常、SurfaceView のコールバック関数で使用されます。

1.1 getHolder() メソッド

SurfaceHolder オブジェクトを取得します。

SurfaceHolder holder = surfaceView.getHolder();

1.2 addCallback() メソッド
SurfaceHolder.Callback コールバック関数を登録します。

holder.addCallback(callback);

1.3 setFixedSize() メソッド

サーフェスのサイズを設定します。

holder.setFixedSize(width, height);

2.SurfaceHolder.Callback
SurfaceHolder.Callback は、SurfaceView ライフサイクル コールバック メソッドを提供するコールバック関数インターフェイスです。

2.1 surfaceCreated()方法

Surface の作成時に呼び出されます。

@Override
public void surfaceCreated(SurfaceHolder holder) {
    // 初始化MediaPlayer等对象
}

2.2 surfaceChanged() メソッド

Surface のサイズまたは形式が変更されたときに呼び出されます。

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    // 更新MediaPlayer等对象的参数
}

2.3 surfaceDestroyed()方法

Surface が破棄されたときに呼び出されます。

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // 释放MediaPlayer等对象
}

3. キャンバス
キャンバスは、SurfaceHolder.Callback コールバック関数で使用できる SurfaceView を描画するために使用されるオブジェクトです。

3.1 lockCanvas() メソッド

Canvas オブジェクトを取得し、描画操作を開始します。

Canvas canvas = holder.lockCanvas();

3.2 drawXXX() メソッド

テキストやグラフィックなどの描画操作を実行します。

canvas.drawText("Hello, world!", x, y, paint);

3.3 unlockCanvasAndPost()方法

抽選作業を終了し、抽選結果を提出します。

holder.unlockCanvasAndPost(canvas);

4. サーフェス
サーフェスは、SurfaceView 内の基になるオブジェクトであり、描画操作のために直接 Surface を操作できます。

4.1 getSurface() メソッド

Surface オブジェクトを取得します。

Surface surface = holder.getSurface();

4.2 setFormat() メソッド

Surface のピクセル形式を設定します。

surface.setFormat(PixelFormat.RGBA_8888);

4.3 setFixedSize() メソッド

サーフェスのサイズを設定します。

surface.setFixedSize(width, height);

5. SetZOrderXXX
setZOrderOnTop および setZOrderMediaOverlay メソッドを使用して、SurfaceView の Z オーダーを設定し、他のビューでの SurfaceView の表示順序を制御できます。

setZOrderOnTop メソッドは、SurfaceView を Z オーダーの一番上に表示し、他のビューをカバーすることができ、通常、ビデオの弾幕などの効果を実現するために使用されます; setZOrderMediaOverlay メソッドは、SurfaceView を通常のビューの上に表示します。ただし、他の SurfaceView の下では、通常、UI コントロールとビデオ プレーヤーのオーバーレイを実装するために使用されます。

どちらのメソッドも、対応する Z オーダーを有効にするかどうかを示すブール値パラメーターを渡す必要があります。true は有効を意味し、false は無効を意味します。例えば:

surfaceView.setZOrderOnTop(true);

これら 2 つのメソッドは、SurfaceView の作成後に呼び出す必要があることに注意してください。そうしないと、無効になります。同時に、Z オーダーを設定した後、SurfaceView のサイズを更新するか、ビューを再描画して、SurfaceView が他のビューの上または下に正しく表示されるようにする必要がある場合があります。

なお、SurfaceView の特殊性により、 setZOrderOnTop メソッドや setZOrderMediaOverlay メソッドを使用すると View の複雑さが増し、パフォーマンスの問題や予期しない問題が発生する可能性があるため、注意して使用し、テストして最適化することをお勧めします。特定のシナリオで。

要するにSurfaceViewのAPIは比較的使いやすいのですが、サブスレッドでの描画操作に注意が必要で、スレッド通信メソッドを使ってUIスレッドとやり取りする必要があります。**同時に、より良いユーザー エクスペリエンスを提供するために、さまざまなアプリケーション シナリオに従ってパラメータを設定および最適化する必要があります。

SurfaceView 動画再生コード

public class VideoSurfaceView extends SurfaceView implements SurfaceHolder.Callback, MediaPlayer.OnPreparedListener, MediaPlayer.OnVideoSizeChangedListener {

    private SurfaceHolder mHolder;
    private MediaPlayer mMediaPlayer;

    public VideoSurfaceView(Context context) {
        super(context);
        initView();
    }

    public VideoSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    private void initView() {
        mHolder = getHolder();
        mHolder.addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setDataSource("http://example.com/video.mp4");
            mMediaPlayer.setDisplay(mHolder);
            mMediaPlayer.setOnPreparedListener(this);
            mMediaPlayer.setOnVideoSizeChangedListener(this);
            mMediaPlayer.prepareAsync();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mMediaPlayer.stop();
        mMediaPlayer.release();
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        mp.start();
    }

    @Override
    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
        if (width != 0 && height != 0) {
            getHolder().setFixedSize(width, height);
        }
    }
}

このサンプル コードでは、SurfaceHolder.Callback、MediaPlayer.OnPreparedListener、および MediaPlayer.OnVideoSizeChangedListener インターフェイスを実装して、SurfaceView の作成と破棄のイベント、およびビデオの準備とサイズ変更のイベントをリッスンします。

surfaceCreated メソッドで MediaPlayer オブジェクトを作成し、データ ソースと表示を SurfaceHolder として設定し、最後に MediaPlayer を非同期で準備します。onPrepared メソッドでビデオの再生を開始します。プレーヤーを停止し、surfaceDestroyed メソッドでリソースを解放します。動画が正常に表示されるように、onVideoSizeChanged メソッドで SurfaceView のサイズを設定します。

実際のプロジェクトでは、エラー処理、再生制御、キャッシュ制御の処理を含む、より完全なビデオ プレーヤーのパッケージ化と処理が必要になることに注意してください。これは単純なサンプル コードであり、実際のニーズを満たすことはできません。

SurfaceView は実際のプロジェクトでシーンを使用します

SurfaceView には、実際の開発における多くの使用シナリオがあります。以下は、いくつかの一般的なアプリケーション シナリオです。

ビデオ プレーヤー: SurfaceView は独立したスレッドでビデオ フレームを描画できるため、パフォーマンスと流暢さが向上します。

カメラ プレビュー: SurfaceView をカメラ プレビューに使用でき、プレビュー プロセス中にリアルタイムの画像処理を実行できます。

ゲーム開発:SurfaceViewはゲーム描画に使用でき、ゲームロジックの処理とレンダリングは独立したスレッドで実行できます。

カスタム描画コントロール: SurfaceView を使用して、より柔軟な描画方法を提供できるカスタム描画コントロールを実装できます。

ネットワーク伝送: SurfaceView はネットワーク伝送に使用でき、独立したスレッドでネットワーク データの受信と表示を処理できます。

なお、SurfaceViewはSurfaceをベースとしているため、Surfaceのライフサイクルやメモリ管理に注意して使用する必要があります。Surface のライフサイクルとメモリを適切に管理しないと、アプリケーションが予期しない動作をしたり、クラッシュしたりする可能性があります。したがって、実際の開発では、アプリケーションの安定性とパフォーマンスを確保するために、SurfaceView の使用シナリオと具体的な実装方法を慎重に検討する必要があります。

おすすめ

転載: blog.csdn.net/u012124438/article/details/129335226
おすすめ