Android 프레임워크는 레이아웃의 루트 노드를 그리고 레이아웃 트리를 측정하고 그린다.
트리를 이동하고, 잘못된 영역을 교차하는 각 View를 렌더링하여 그린다.
각 ViewGroup은 draw() 메소드를 사용하여 각 하위 요소를 그리도록 요청하고 각 View는 자체 그리기를 담당한다.
뷰를 그리는 과정 3가지 과정은 다음과 같다.
- Measure : 뷰의 크기를 정함 / 측정계
- Layout : 뷰의 위치를 정함 / 좌표계
- Draw : 뷰를 캔버스 위에 실제 그리는 과정
뷰의 좌표계를 설정하는 단계는 Measure 단계이다. 또한 뷰의 좌표계를 사용하는 단계는 Layout 단계와 Draw 단계이다.
뷰의 좌표계를 사용하는 단계에서는 이미 뷰의 좌표계가 정의되어 있다.
안드로이드 뷰는 혼자서 존재할 수 없다. 반드시 뷰그룹(ViewGroup)에 담겨있어야 한다.
=> 측정 단계가 반드시 필요함 / 즉, 자신의 주변과 자기 자신의 정보를 측정
ViewGroup은 자식뷰들을 감싸고 있기에, 자신을 그릴 필요가 없다. (ViewGroup일 경우에는 onDraw가 호출이 안 될 경우 있다.)
View의 LifeCycle
시작하기
- onAttachedToWindow()
View가 Window에 연결될 때 호출되며, 뷰가 화면에 표시될 준비가 되었음을 알린다.
View 초기화 작업을 수행하는 데 사용할 수 있다.
addView() 함수를 호출하여 View를 View 그룹에 추가할 때 호출한다.
측정하기
- measure() / onMeasure()
이 단계에서 뷰의 크기가 결정된다.
measure() 메소드는 시스템에 의해 호출되며 실제 크기 계산은 onMeasure()에서 수행된다.
개발자는 뷰의 크기를 MeasureSpec 제약 조건 내에서 결정해야 한다.
onMeasure() 메소드를 오버라이드하여 자식 View의 크기를 고려하여 View의 크기를 지정할 수 있다.
배치하기
- layout() / onLayout()
View의 위치가 부모 내에서 결정된다.
layout() 메소드는 뷰의 위치를 설정하고, onLayout()을 통해 위치 설정 로직을 구현한다.
onLayout() 메소드를 오버라이드하여 자식 View의 위치를 지정할 수 있다.
onLayout() 메소드는 ViewGroup에 대해 자식 뷰의 정확한 위치를 배치하는데 사용된다.
그리기
- draw() / onDraw()
뷰의 그리기 작업이 수행된다.
draw() 메소드는 뷰의 배경, 자신의 내용, 자식 뷰들 , 그리고 전경을 그린다.
onDraw() 메소드는 개발자가 커스텀 뷰를 그리기 위해 오버라이드 할 수 있으며, 뷰의 실제 내용을 그린다. - dispatchDraw()
ViewGroup에 정의되어 있으며, ViewGroup에서 자식 뷰들의 그리기를 관리한다.
하위 뷰를 그리기 위해 draw()에 의해 호출되며 현재 View와 그 안에 포함된 모든 자식 View를 그린다.
onDraw() 메소드가 끝난 후에 호출되며 오버라이드하여 뷰 그리기 순서를 제어하거나 드로잉 이벤트를 처리한다.
실제로 draw() 메소드 호출은 layout() 메소드가 실행되어 위치가 설정된 직후 바로 이루어지는 것은 아니다.
layout() 과정이 완료된 후, 뷰가 그려질 준비가 되면 시스템은 뷰의 draw() 메소드를 호출한다.
따라서 draw() 메소드는 뷰의 전체적인 그리기 프로세스를 관리하며, 이 과정에서 onDraw()를 사용해 뷰의 주요 내용을 그리고, dispatchDraw()를 사용해 ViewGroup의 경우 자식 뷰들을 순차적으로 그리는 것이다.
무효화
- invalidate()
View 클래스에 정의된 메소드로써, 호출될 때 현재 뷰를 무효화한다.
뷰의 현재 상태가 더 이상 유효하지 않으며 다시 그려져야 함을 알리는 신호로 작용한다.
뷰의 상태가 변경되어 그 내용이 더 이상 유효하지 않고 화면에 다시 그려져야 할 때 발생한다.
이후 다시 draw() 메소드가 호출되며 변경 사항을 다시 그린다.
앱이 처음 로딩될 때는 뷰의 초기 상태가 설정되고, 이 과정에서 각 뷰는 처음으로 그려진다.
이 때는 뷰가 처음으로 화면에 나타나기 때문에, 뷰의 상태는 최신 상태로 간주되어 무효화 과정을 거치지 않는다.
이후 초기 그리기 과정에서 뷰의 onMeasure(), onLayout(), draw() 메소드가 순차적으로 호출되며 화면에 그려진다.
다시 계산하기
- requestLayout()
View 또는 ViewGroup의 레이아웃이 변경될 필요가 있음을 시스템에 알리는 데 사용된다.
이 메소드가 호출되면 시스템은 해당 뷰의 measure 및 layout 과정을 다시 수행하도록 한다.
뷰나 뷰 그룹의 크기나 위치 등의 레이아웃 파라미터가 변경될 때 호출된다.
이때 뷰 트리 내에서 해당 뷰와 그 부모 뷰들을 통해 새로운 레이아웃 계산을 시작한다.
+ onMeasure()가 여러번 출력되는 현상
시스템이 좌표를 측정하는 과정에서 정확하게 계산이 될 때까지 onMeasure()를 호출한다는 것 같다.
정확하게 아시는 분 있으면 댓글 부탁드립니다.
'Android' 카테고리의 다른 글
[Android] Fragment에서 Binding 객체를 null로 설정해야 하는 이유 (1) | 2024.03.15 |
---|---|
[Android] ViewBinding 총 정리 (2) | 2024.03.14 |
[Android] ViewPager2에 대해서 feat.RecyclerView (0) | 2024.03.10 |
[Android] 내가 쓰려고 모아놓은 색상코드 - color.xml (0) | 2024.03.09 |
[Android] RecyclerView와 ListAdapter (1) | 2024.03.08 |