출처 : http://luxtella.tistory.com

결론은 두가지 방법이 있다.
1. View의 canvas가 그림을 framebuffer가 아닌 bitmap에 그리게 하기
2. View.getDrawingBuffer() 이용하기

우선 성능 측면에서는 1번이 약간 앞선다. 두가지 방법의 메카니즘을 설명해보자

1. View의 canvas가 그림을 framebuffer가 아닌 bitmap에 그리게 하기

우선 사용법은

View를 상속받아  onDraw를 overriding하면 그림을 screen(framebuffer겠죠?)에 그리지 않고 bitmap에 그릴수 있다

public void onDraw(Canvas canvas){
canvas.setBitmap(bitmap);
bitmap.eraseColor(Color.WHITE);
super.onDraw(canvas);
}

위의 코드처럼 bitmap을 하나 잡아서 그것을 canvas에 장착시키면 그림을 bitmap에 그린다. screen에는 안그리므로 까만화면이 나올 뿐이다.

View ----------- canvas ----framebuffer
              Draw                     |---bitmap

즉 canvas 가 그리는 곳을 bitmap으로 살짝 틀어줌으로서 그림이 그려진 memory를 얻을수 있다.
참고로 Draw가 onDraw를 다시 콜한다. 지난 포스트를 참고하자.


2. View.getDrawingBuffer() 이용하기

우선 getDrawingCache의 내부구현을 보면
View.getDrawingCache
                canvas = softref.get(); //cavas를 softReference로 만들어놓고 쓸때 꺼냅니다. 
                bitmap = createBitmap(width, height, config); //이놈이 jni로 c로 가서 SkBitmap을 새로 alloc합니다. 가장 병목인 곳
canvas.setBitmap(bitmap);
bitmap.eraseColor(Color.WHITE);
draw(canvas);
즉 bitmap공간을 새로 잡고 그것을 별도로 사용하는 canvas에 붙여서 그림을 bitmap에 직접 그린다. 전자와 mechanism은 같지만 bitmap을 새로 alloc한다는 단점이 있다.

앞에 그림에서 앞에 몇가지 과정이 더붙은 모양세다

View ---------------------------------- View ----------- canvas ---- bitmap
          getDrawingCache -- canvas.setBitmap                        Draw 

원래 View의 그림도 그린다면 getDrawingCache다 View.draw를 콜하고 원래 그림을 그리는 쓰래드도 View.draw를 콜하므로 똑같은 그림을 그리기 위해 두번 연산하게 된다.



참고로
 - softReference란 cache를 만들때 java에서 잘 사용하는 기법인데, 오직 메모리가 모자를때 garbage collector에 의해 메모리가 해제됩니다. 즉 메모리를 많이 차지하면서 계속써야되는놈을 softReference로 만들어놓으면 out of memory로 app이 중지하는것을 방지할 수 있습니다.
 - Android의 canvas, bitmap, paint 등의 그림을 그리는 class들이 skia의 SkCanvas, SkBitmap, SkPaint들과 거의 1:1로 매핑되어있네요.

+ Recent posts