2012년 7월 4일 수요일

Picture Class는 무엇에 쓰는 물건?

결론은 당신의 View가 canvas를 채우기 위해 jni pass를 하는 연산이 많이 수행된다면 Picture로 한번 canvas를 감싸는것을 고려해 볼수 있다.


developer.android.com의 Picture 설명을 보면

A picture records drawing calls (via the canvas returned by beginRecording) and can then play them back (via picture.draw(canvas) or canvas.drawPicture). The picture's contents can also be written to a stream, and then later restored to a new picture (via writeToStream / createFromStream). For most content (esp. text, lines, rectangles), drawing a sequence from a picture can be faster than the equivalent API calls, since the picture performs its playback without incurring any java-call overhead.




JNI콜의 오버해드를 줄일수 있다고 나온다. 왜그럴까?



http://www.androidjavadoc.com/1.0_r1_src/android/graphics/class-use/Picture.html 를 보면 수많은 View중 굳이 WebView만이 Picture class를 이용해서 그림을 그린다. 그 이유는 WebView의 canvas에 그림을 채우기 위해 WebKit의 Render Object에 수많은 함수 콜을 해야 할 것이다. 그러면 jni의 overhead가 걸릴텐대 그래서 Picture를 쓴다.

어떻게 Picture가 jni의 overhead를 없에는지 설명해보자

우선 사용법부터 설명하면

보통은 View의 Draw를 overriding할때
Draw(canvas) {
super.onDraw(canvas);
}
일텐데 Picture를 사용하면
Draw(canvas) {
super.onDraw(mPicture.beginRecording(getWidth(), getHeight());
mPicture.endRecording();

canvas.drawPicture(mPicture);
}
라는 식으로 코딩을 하게 된다.

한마디로 Picture의 member variable canvas에 View의 child들을 순회하면서 그림을 그린뒤
Picture의 canvas를 대빵 View의 canvas가 받아서 한꺼번에 그리는 것이다.

중간에 중개자가 끼었는데 속도가 오히려 빨라진다? 가 이상하게 느껴질수 있는데.. jni의 overhead를 상쇄하므로써 속도에 이익을 얻는것이 결론이다.

Android의 모든 graphic library는 Skia library와 거이 1:1 매핑된다. 
한마디로 어떤 Class의 method를 쓰더라도  jni를 거쳐서 skia가 실행하는것이다.

Picture.beginRecording을 하면 jni밑에 C에서 SkPicture가 SkCanvas의 instance가 그림을 그릴 준비를 한다. 그 뒤 Picture.beginRecording에 그림을 그리면 java까지 올라올 필요 없이 C에서 skia로 그림을 그린다.. jni오버해드가 사라지는 지점이다. 그림을 다 그리면 java에서 Picture의 canvas를 가지고 그림을 그리는것이다.

결론

1. jni오버해드를 줄이고 싶을때  Picture를 써라
2. View의 그림을 변형해서 여러번 그리고 싶을때 Picture를 써라 (가령 거울대칭으로 그림을 그리고 싶다 등등)

댓글 없음:

댓글 쓰기