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에서 사용 가능한 데이터를 기반으로 로직을 작성해야 한다.

 

Buy me a coffeeBuy me a coffee
카테고리: AndroidTutorial

0개의 댓글

답글 남기기

이메일은 공개되지 않습니다.