SurfaceView & Double Buffering

zerolism ㅣ 2012. 4. 30. 10:20

SMALL

안드로이드 역시 더블 버퍼링을 기본적으로 제공합니다.


1. 생성자에서 ContentView를 생성시 R 클래스를 통한 것이 아니라 SampleView 인스턴스를 직접 할당하고 있습니다.

2. SampleView는 SurfaceView를 상속하며 SurfaceHolder.Callback 인터페이스를 구현합니다. SurfaceView는 그래픽을 표현할 자리를 제공해주는 View라고 보시면 되겠습니다. 3D 그래픽을 표현할 때도 많이 사용됩니다.

3. SurfaceView의 Surface에 접근하기 위해서 SurfaceHolder를 경유합니다.

4. SurfaceHolder는 Surface의 생명주기에 맞는 콜백 메카니즘을 제공합니다. 콜백 인터페이스는 다음과 같음 메소드를 정의하고 있습니다.

- surfaceCreated: Surface 생성 후 호출됨.
- surfaceChanged: Surface 가 변경되었을 경우 호출됨.

- surfaceDestroyed: Surface가 Destroy된 경우 호출됨. 여기서 필요한 자원 해제 작업을 수행.


5.SurfaceHolder#lockCanvas() & SurfaceHolder#unlockCanvasAndPost(Canvas c)


더블 버퍼링은 스윙이나 OpenGL에서도 사용되는 고전적인 방법으로 애니메이션과 같이 여러 이미지를 번갈아 보여주어야 하는 경우 Back-Buffer에 이미지를 미리 그린 다음 화면에 바로 표시하여 이미지 처리 성능을 향상 시키는 방법입니다. 

안드로이드에서도 역시 더블 버퍼링을 제공하고 있습니다. lockCanvas를 통해 얻어진 Canvas에 그림을 그리는 것은 Back-Buffer에 그리는 것으로 화면에 전혀 표시되지 않습니다. 반드시 unlockCanvasAndPost를 수행해주어야 비로소 작성된 이미지는 화면에 표현됩니다. 따라서 애니메이션 처리를 하시려면 애니메이션 관련 루프 내에서 lockCanvas와 unlockCanvasAndPost룰 반복적으로 수행해야 합니다.



public class SurfaceViewTest extends Activity {

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(new SampleView(this));

    }

    

    private static class SampleView extends SurfaceView 

    implements SurfaceHolder.Callback {


        public SampleView(Context context) {

            super(context);

            SurfaceHolder holder = getHolder();

            holder.addCallback(this);

        }


        public void surfaceCreated(SurfaceHolder holder) {

            Canvas canvas = holder.lockCanvas();

            try {

                Paint fontPaint = new Paint();

                fontPaint.setTextSize(15f);

                fontPaint.setColor(Color.WHITE);

                canvas.drawText("Wilddog's SurfaceView Test", 10, 40, fontPaint);

            } finally {

                if (canvas != null)

                    holder.unlockCanvasAndPost(canvas);

            }

        }

        public void surfaceChanged(SurfaceHolder holder, int format, int width,

int height) {}


        public void surfaceDestroyed(SurfaceHolder holder) {}

    }

}



public abstract Canvas lockCanvas ()

Since: API Level 1

Start editing the pixels in the surface. The returned Canvas can be used to draw into the surface's bitmap. A null is returned if the surface has not been created or otherwise can not be edited. You will usually need to implement Callback.surfaceCreated to find out when the Surface is available for use.

The content of the Surface is never preserved between unlockCanvas() and lockCanvas(), for this reason, every pixel within the Surface area must be written. The only exception to this rule is when a dirty rectangle is specified, in which case, non dirty pixels will be preserved.

If you call this repeatedly when the Surface is not ready (before Callback.surfaceCreated or after Callback.surfaceDestroyed), your calls will be throttled to a slow rate in order to avoid consuming CPU.

If null is not returned, this function internally holds a lock until the corresponding unlockCanvasAndPost(Canvas) call, preventing SurfaceViewfrom creating, destroying, or modifying the surface while it is being drawn. This can be more convenience than accessing the Surface directly, as you do not need to do special synchronization with a drawing thread in Callback.surfaceDestroyed.

Returns
  • Canvas Use to draw into the surface.

public abstract void unlockCanvasAndPost (Canvas canvas)

Since: API Level 1

Finish editing pixels in the surface. After this call, the surface's current pixels will be shown on the screen, but its content is lost, in particular there is no guarantee that the content of the Surface will remain unchanged when lockCanvas() is called again.

Parameters
canvasThe Canvas previously returned by lockCanvas().
See Also




LIST