https://proandroiddev.com/the-life-cycle-of-a-view-in-android-6a2c4665b95e을 번역한 내용입니다.
안드로이드 앱을 실행할 때 우리가 가장 먼저 스크린에서 볼 수 있는 것이 View라고 말할 수 있다.
View 클래스는 사용자 인터페이스 기본적인 구성 요소를 가지고 있다. 예를들어 스크린위 사각형 영역에서 그리기 및 이벤트 처리 같은 작업이 View를 통해 이루어진다. View는 Button, TextView, ImageView 등의 위젯을 작성하는 데 사용되는 기본 클래스 . View의 또 다른 서브클래스인 ViewGroup은 보이지는 않는 컨테이너로써 다른 View들을 다른 View(또는 다른 ViewGroup)들을 포함 할 수 있다.
View의 생명주기
모든 액티비티는 생명주기를 가지고 있는데, View도 생명주기를 가지고 있다. 화면에 렌더링 된 View는 다음 그림과 같은 생명주기 메서드를 거쳐 화면에 그려진다. 각 메서드에는 중요한 의미가 있다. 생명주기에 대해서 알아보자.
생성자(Constructors)
보통 Custom View를 만들 때 어떤 생성자를 구현 하는지 혼란스럽다.
View(Context context)
View(Context context, @Nullable AttributeSet attrs)
View(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)
View(Context context)
코드에서 View를 동적으로 만들 때 사용하는 간단한 생성자다. 여기서 매개 변수 context는 뷰가 실행될 때 현재 테마, 리소스 등을 구성하는데 사용된다.
View(Context context, @Nullable AttributeSet attrs)
XML에서 View를 전개(Inflation) 할 때 호출되는 생성자로, XML 파일에서 지정된 속성을 제공하여 XML 파일에서 View를 구성 할 때 호출된다. 이 생성자는 기본 스타일인 0을 사용하므로 컨텍스트의 테마 및 지정된 AttributeSet의 속성 값만 적용된다.
View(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
XML을 통해 전개를 하고 테마 속성에서 클래스별 기본 스타일을 적용한다. 이 View 생성자는 서브 클래스가 전개할 때 자체 기본 스타일을 사용할 수 있도록 한다. 예를 들어, Button 클래스의 생성자는 수퍼 클래스 생성자를 호출하고 defStyleAttr에 R.attr.buttonStyle을 제공한다. 이를 통해 테마의 버튼 스타일은 모든 기본 View 속성 (특히 배경)과 Button 클래스의 속성을 수정할 수 있다.
defStyleAttr 매개 변수는 View의 기본값을 제공하는 Style 리소스 대한 참조를 포함하는 현재 테마의 속성이다. 기본값을 찾지 않으려면 0으로 지정할 수 있다.
View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)
XML을 전개하고 테마 속성 또는 Style 리소스에서 클래스 별 기본 스타일을 적용한다. 이 생성자는 서브 클래스가 전개할 때 자체 기본 스타일을 사용할 수 있도록한다. 위와 유사하다.
매개변수 defStyleRes는 View의 defStyleAttr가 0이거나 테마에서 찾을 수 없는 경우에만 기본값을 제공하는 Style 리소스 ID다. 기본값을 찾지 않으려면 0 으로 지정한다.
Attachment / Detachment
View가 Window에서 연결되거나 분리 될 때의 단계다. 이 단계에는 적절한 작업을 수행하기 위해 콜백을 받는 몇 가지 방법이 있다.
onAttachedToWindow()
View가 Window에 연결되면 호출된다. View가 활성화 될 수 있고, 드로잉 할 표면이 있음을 알고있는 단계다. 따라서 리소스 할당을 시작하거나 리스너를 설정할 수 있다.
onDetachedFromWindow()
View가 Window에서 분리 될 때 호출된다. 이 시점에서 더 이상 드로잉을 할 표면이 없다. 예약 된 자원을 정리하거나 정리하는 모든 종류의 작업을 중지해야하는 곳디다. 이 메소드는 ViewGroup에서 View제거를 호출하거나 액티비티가 Destroyed 될 때 호출된다.
onFinishInflate()
이 메소드는 View가 전개가 끝날 때 호출된다. 레이아웃의 경우 모든 Child View가 추가 된 후에 호출된다.
순회(Traversals)
View 계층 구조는 부모 노드 (ViewGroup)에서 분기가있는 리프 노드 (Child Views)의 트리 구조와 같기 때문에 순회 단계라고 한다. 따라서 각 메소드는 부모에서 시작하여 마지막 노드까지 순회하여 제약 조건을 정의한다.
Measure 단계와 Layout 단계는 항상 위와 같이 순차적으로 진행된다.
onMeasure()
View의 크기를 확인하기 위해 호출됩니다. ViewGroup의 경우 계속해서 각 Child view에 대한 측정을 하고, 그에 대한 결과로 자신의 사이즈를 결정한다.
onMeasure(int widthMeasureSpec, int heightMeasureSpec)
@param widthMeasureSpec 부모뷰에 의해 적용된 수평 공간 요구사항
@param heightMeasureSpec 부모뷰에 의해 적용된 수직 공간 요구사항
onMeasure ()는 값을 반환하지 않고, setMeasuredDimension()을 호출하여 너비와 높이를 명시적으로 설정한다.
MeasureSpec
MeasureSpec은 부모에서 자식으로 전달되는 레이아웃 요구 사항을 캡슐화한다. 각 MeasureSpec은 너비 또는 높이에 대한 요구 사항을 나타낸다. MeasureSpec은 크기와 모드로 구성되며, 세 가지 모드가 있다.
MeasureSpec.EXACTLY : 부모뷰가 자식뷰의 정확한 크기를 결정한다. 자식뷰의 사이즈와 관계없이 주어진 경계내에서 사이즈가 결정된다.
MeasureSpec.AT_MOST : 자식뷰는 지정된 크기까지 원하는 만큼 커질 수 있다.
MeasureSpec.UNSPECIFIED : 부모뷰가 자식뷰에 제한을 두지 않기 때문에, 자식뷰는 원하는 크기가 될 수 있다.
onLayout()
뷰를 측정하여 화면에 배치 한 후에 호출된다.
onDraw()
크기와 위치는 이전 단계에서 계산되므로 View는 그것들을 기준으로 그릴 수 있습니다. onDraw(Canvas) 메서드에서 생성된 캔버스 객체에는 GPU로 보낼 OpenGL-ES 명령목록(displayList)이 있다. onDraw()는 여러번 호출되므로 이이곳에서객체를 만들면 안된다.
특정 뷰의 속성이 변경되었을 때 실행되는 두 가지 메서드가 있다(invalidate(), requestLayout())
invalidate()
invalidate ()는 변경 사항을 보여주고자 하는 특정뷰에 대해 강제로 다시 그리기를 요구하는 메소드이다. 뷰 모양이 변경되면 invalidate()를 호출해야한다고 간단히 말할 수 있다.
requestLayout()
어떤 시점에서 뷰의 경계가 변경되었다면, View를 다시 측정하기 위해 requestLayout()을 호출하여 Measure및 Layout 단계를 다시 거칠 수 있다.
View에서 메소드를 호출 할 때는 항상 UI 스레드내에서 수행해야한다. 다른 스레드에서 작업하고 있고, 해당 스레드에서 View의상태를 업데이트 하려는 경우 핸들러를 사용해야한다.
상태의 저장과 복구(State Save / Restore)
onSaveInstanceState()
먼저 상태를 저장하려면 ID를 제공해야 한다. View 계층에 동일한 ID를 가진 여러 개의 뷰가있는 경우 고유한 ID를 지정하여 모든 상태를 저장할 수 있도록 한다.
둘째, View.BaseSavedState를 확장하여 속성값을 저장하는 클래스가 필요하다. 이해를 돕기 위해 아래에 예제 코드가 준비되어 있다.
onRestoreInstanceState(Parcelable state)
여기서는 이 onRestoreInstanceState메서드를 재정의하고 Parcelable에서 데이터를 읽은 다음 Parcelable에서 사용 가능한 데이터를 기반으로 로직을 작성해야 한다.
4개의 댓글
Jeremih · 2021년 5월 8일 11:46 오후
정말 딱 알고싶은정보가 그대로있네요
항상 감사합니다!
297 · 2022년 2월 16일 8:28 오후
잘 읽었습니다!
카지노사이트제작 · 2023년 6월 10일 5:10 오전
Im obliged for the blog post.Thanks Again. Fantastic.
성빈 · 2023년 6월 27일 5:59 오후
멋진 글 감사합니다!