WMS:Exibição de desenho do SurfaceView


1. Uso do controle SurfaceView

1.1 Coreógrafo aceita sinal VSync

Choreographer é um canal fornecido pelo Android para obter sinais VSync. O controle aqui SurfaceViewdesenha ativamente na tela e, em aplicativos gerais como o
Choreographer no WMS, ao adicionar uma interface com o sinal de interrupção VSYNC, ele inicia a partir do método scheduleTraversals do ViewRootImpl e adiciona internamente a tarefa de desenho ao Choreographer por meio do postCallback do Choreographer.

Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
    
    
            @Override
            public void doFrame(long frameTimeNanos) {
    
    //当vsync信号来时会调用到这里
                mHandler.sendEmptyMessage(MyHandler.TAG_UPDATE_TEXT);
                Choreographer.getInstance().removeFrameCallback(this);
                Choreographer.getInstance().postFrameCallback(this);
            }
        });

1.2 SurfaceView personalizado

  • MySurfaceViewColoque-o no construtor mSurfaceHolder = this.getHolder()e configure-oSurfaceHolder.Callback
  • Herdar Runnable, Threadexecutar e Global.syncCondition.await();aguardar aqui a mensagem de notificação da chegada do vsync
  • Processamento simultâneo de thread Locke Condition:
public class Global {
     
     
   public static ReentrantLock lock = new ReentrantLock();
   public static Condition syncCondition = lock.newCondition();

   private Global() {
     
     
   }
}
  • Choreographer#doFrameNotificar Global.syncCondition.signal();outro tópico para atualizar a tela

com/xhbruce/ui/MySurfaceView.java

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    
    

    private static String TAG = "MySurfaceView";
    private SurfaceHolder mSurfaceHolder;
    private int autoNum = 0;
    private Paint mPaint = new Paint();

    public MySurfaceView(Context context) {
    
    
        this(context, null);
    }

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

    public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
    
    
        super(context, attrs, defStyleAttr);
        mSurfaceHolder = this.getHolder();
        mSurfaceHolder.addCallback(this);
        Log.d(TAG, "MySurfaceView(3) holder=" + mSurfaceHolder.toString());
    }

    public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    
    
        super(context, attrs, defStyleAttr, defStyleRes);
        mSurfaceHolder = this.getHolder();
        mSurfaceHolder.addCallback(this);
        Log.d(TAG, "MySurfaceView(4) holder=" + mSurfaceHolder.toString());
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder holder) {
    
    
        Log.d(TAG, "surfaceCreated() holder=" + holder.toString());
        new Thread(this).start();
//        draw();//画蓝色或绿色
    }

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

    }

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

    }

    @Override
    public void run() {
    
    
        while (true) {
    
    
            Log.d(TAG, "run() autoNum=" + autoNum);
            Global.lock.lock();
            try {
    
    
                Global.syncCondition.await();//在这里等待vsync到来的通知消息
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            } finally {
    
    
                Global.lock.unlock();
            }
            draw();//画蓝色或绿色
        }
    }

    private void draw() {
    
    

        Canvas mCanvas = null;
        try {
    
    
            mCanvas = mSurfaceHolder.lockCanvas();
            if (autoNum % 2 == 0) {
    
    
                mPaint.setColor(Color.BLUE);//如果为双数则画面画成蓝色
            } else {
    
    
                mPaint.setColor(Color.GREEN);//如果为单数则画面画成绿色
            }
            mCanvas.drawRect(0, 0, getRight(), getBottom(), mPaint);
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if (mCanvas != null) {
    
    
                mSurfaceHolder.unlockCanvasAndPost(mCanvas);
            }
        }
        Log.d(TAG, "draw() autoNum=" + autoNum);
        autoNum++;//数字加1
    }
}

Arquivos de atividade e layout xml correspondentes:
com/xhbruce/surfaceviewtest/MySurfaceViewTest.java

public class MySurfaceViewTest extends AppCompatActivity {
    
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_surface_view_test);

        Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
    
    
            @Override
            public void doFrame(long frameTimeNanos) {
    
    //当vsync信号来时会调用到这里
                Global.lock.lock();
                try {
    
    
                    Global.syncCondition.signal();//通知另一条线程更新画面
                } catch (Exception e) {
    
    
                    e.printStackTrace();
                } finally {
    
    
                    Global.lock.unlock();
                }
                Choreographer.getInstance().removeFrameCallback(this);
                Choreographer.getInstance().postFrameCallback(this);
            }
        });
    }
}

layout/atividade_minha_superfície_view_test.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MySurfaceViewTest">

    <com.xhbruce.ui.MySurfaceView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

1.3 Resultados

Demonstração do SurfaceView

2. SurfaceView obtém a tela e a exibe

  • SurfaceHolder.lockCanvas() obtém o objeto Canvas e bloqueia a tela
  • SurfaceHolder.unlockCanvasAndPost(Canvas canvas) encerra o desenho bloqueado, envia as alterações e exibe os gráficos.

2.1 SurfaceHolder.lockCanvas()

A função finalmente chamada pelo método lock do Surface GraphicBufferProducerobtém dequeueBufferum Slot. Se o Slot não tiver um GraphicBuffer alocado, será alocado um GraphicBuffer neste momento e, em seguida, um sinalizador com uma marca será retornado. BUFFER_NEEDS_REALLOCATIONDepois que o lado do aplicativo vir este sinalizador , ele passará as interfaces requestBuffer e importBuffer.Mapeie GraphicBuffer para seu próprio espaço de processo.

Insira a descrição da imagem aqui

2.2 SurfaceHolder.unlockCanvasAndPost (tela de tela)

SurfaceView usa dois Canvas, one frontCanvase one backCanvas, ao atualizar a visualização. O frontCanvas é exibido a cada vez, e o backCanvas armazena a visualização antes da última alteração. Ao usar lockCanvas() para obter a tela, o que você obtém é, na verdade, backCanvas. do frontCanvas exibido. Em seguida, você desenha uma nova visualização no backCanvas obtido e, em seguida, unlockCanvasAndPost(Canvas canvas)esta visualização, a tela carregada substituirá o frontCanvas original como o novo frontCanvas, e o frontCanvas original mudará para o plano de fundo como backCanvas.

Insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/qq_23452385/article/details/132306539
Recomendado
Clasificación