-
[ Android ] customView의 onDraw 함수 디버깅 기록Android & Kotlin 2022. 3. 4. 14:37
1. 문제 상황
CumtomView 특정 점이 터치가 되면 리스너로 View(MVP 모델의 ) 전달하고 해당 위치 데이터를 이용해 Presenter 를 거쳐 Model을 업데이트 한 뒤 다시 model 의 바뀐 내용대로 포문을 돌면서 커스텀 뷰를 그렸다.
즉 다시말해 customView 밖에서 리스트를 순회하면서 customView의 onDraw 및 invalidate() 를 여러번 호출 상황이었다.
그런데 커스텀뷰가 잘 그려질 때도 있고 그려지지 않을 때도 있었다.
특히 모델의 데이터 즉 리스트가 커질 수록 이 문제는 두드러지게 나타났다.
data의 흐름을 따라 디버깅을 해도 별 문제가 없었고 하루를 통째로 날렸다. ㅜㅜㅜ
// 문제가 발생하던 코드
// 이하 Activity // ... override fun showRectangle(rectangleList: MutableList<Rectangle>) { rectangleList.forEach { myCanvas.drawRectangle(it) } } // 이하 MyCanvas -> cusotmview // ... fun drawRectangle(rec: Rectangle) = with(rec) { rect =createRectF(rec) if (rec == selectedRectangle) { paint.apply { this.style = Paint.Style.STROKE this.color = Color.BLACK } } else { paint.apply { this.style = Paint.Style.FILL this.color = Color.argb(getAlpha(), rgba.r, rgba.g, rgba.b) } } paint.color = Color.argb(getAlpha(), rgba.r, rgba.g, rgba.b) invalidate() } public override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) canvas?.drawRect(rect, paint) }
2. 원인 파악
문제는 View 생성주기에 대한 이해부족으로 invalidate()를 남발한 것이 었다. 아래 view 생명주기를 고려하여 위 코드를 살펴보면
1. 리스트에서 invalidate() 를 호출한다.
2. 이에따라 dipatchToDraw() 부터 호출해나간다.
3. onDraw 까지 다 마치지 않은 상황에서 다음 리스트 원소를 받아 또 invalidate() 를 실행
즉 정상동작할때는 onDraw() 가 끝나는 시점이 리스트의 다음 원소에 접근해 invlidate() 를 호출하는 시점보다 먼저일때였고 이상이 있을때는 반대였던 것이다.
3. 해결 방안
invalidate() 를 한번만 호출 하면되는 상황을 만들면 되었다.
기존에 리스틀 customView 내부로 가져와서 onDraw 안에서 순회하면서 그려나가고 모든 작업이 끝났을때 invalidate() 를 호출함으로써 해결할 수 있었다.
// customView class MyCanvas(context: Context,) : View(context) { fun drawRectangle(recList: MutableList<Rectangle>) { rectangles = recList invalidate() } public override fun onDraw(canvas: Canvas?) { selectedRectangles.forEach { val paint = setBorderPaint(it) rect = createRecF(it) canvas?.drawRect(rect, paint) } super.onDraw(canvas) }
class MainActivity : AppCompatActivity(), CanvasContract.View { private lateinit var binding: ActivityMainBinding lateinit var canvasPresent: Present lateinit var myCanvas: MyCanvas ... override fun showRectangle(rectangleList: MutableList<Rectangle>) { myCanvas.drawRectangle(rectangleList) } }
'Android & Kotlin' 카테고리의 다른 글
[ Android ] 이미지 라이브러리 분석 : Glide (0) 2022.05.04 [ Android ] CustomView 필요성 및 구현 방법 (Kotlin) (0) 2022.03.04 [ Android ] startActivityForResult deprecated 이유와 대안( Activity Result API) (0) 2022.02.15 [ 코틀린 ] 코루틴2 : Coroutine 사용하기 - 기초 (0) 2022.02.02 [ 코틀린 ] 코루틴1 : Coroutine 이해하기 (0) 2022.02.02