Coaspe

Flutter - RenderObject 본문

Flutter/API

Flutter - RenderObject

Coaspe 2023. 2. 17. 13:57

렌더 트리에 있는 객체 입니다.

RenderObject 클래스 계층은 렌더링 라이브러리 존재 이유의 핵심입니다.

영상 요약

위젯 트리는 보이지 않지만 렌더 트리를 사용한다.

요소트리는 렌더 트리를 만들고 그것을 위젯 트리와 동기화시키고 프레임마다 존재하게 한다.

렌더 레이어는 레이아웃, 페인팅, 히트 테스팅을 수행하고, 화면에 보이는 건 모두 렌더 객체들이다.

 

RenderObjectparent를 가집니다. 그리고 자식의 위치와 같은 자식의 구체적인 데이터를 부모 RenderObject가 저장할 수 있는 parentData이라는 슬롯도 가지고 있습니다. RenderObject 클래스는 기본 layout, paint 프로토콜을 구현합니다.

 

그러나 RenderObject 클래스는 자식 모델(e.g. 노드가 0개, 1개 또는 더 많은 자식을 가지고 있는지)을 정의하지 않습니다. 좌표 시스템(e.g. 자식들이 직교 좌표계에 있는지, 극 좌표계에 있는지) 과 구체적인 layout 프로토콜(e.g. 레이아웃이 width-in-height-out 또는 constraint-in-size-out인지 여부 또는 부모가 자식의 레이아웃 전이나 후에 자식의 크기와 위치를 설정하는지 여부 등, 또는 실제로 자식이 부모의 parentData을 읽을 수 있는지)도 정의하지 않습니다.

 

RenderBox 서브클래스는 직교 좌표를 사용하는 레이아웃 시스템으로 그런 프로토콜을 정의합니다.

 

Lifecycle

RenderObject는 더 이상 필요하지 않으면, 반드시 dispose 되어야 합니다. 이 객체를 생성한 객체(이하 creator)는 dispose 할 책임이 있습니다. 일반적으로, 그 creator RenderObjectElement이고, 그 element는 언마운트 될 때 자신이 생성한 RenderObject를 dispose 합니다.

 

RenderObject dispose가 호출 될 때, Picture or Image 객체들 같이 비싼 리소스들을 정리해야 합니다. 정리해야하는 객체들은 렌더 객체가 직접적으로 만드는 모든 Layers를 포함합니다. dispose의 구현의 베이스 layer 속성을 null로 만드는 것 입니다. 서브클래스들도 반드시 자신이 직접 만드는 모든 layer를 null로 만들어야 합니다.

 

Writing a RenderObject subclass

대부분의 경우에, RenderObject를 서브클래싱하는 것 자체로 필요 이상으로 지나치며, RenderBox를 사용하는 것이 좋은 출발점이 될 것입니다. 그러나, 만약 렌더 객체에 직교 좌표계를 사용하고 싶지 않다면, RenderObject를 직접 상속해야 합니다. 직접 상속하는 것은 BoxConstraints를 사용하는 대신 Constraints의 새로운 서브클래스를 사용하고, Size가 아닌 출력 값을 나타내기 위해 완전히 새로운 객체 및 값의 집합을 사용하여 자체 레이아웃 프로토콜을 정의할 수 있습니다. 이런식으로 향상된 유연성은  RenderBox의 기능에 의존할 수 없는 대가를 치르게 됩니다. 예를 들면, RenderBox는 자식을 완전히 layout하지 않고도 자식의 크기를 측정할 수 있는 sizing 프로토콜을 가지고 있습니다. 그 프로토콜은 자식의 크기가 바뀌면, 부모가 다시 layout 되는 방법으로 진행됩니다.(자식의 새로운 차원을 레이아웃에 고려하기 위해서)

 

 RenderBox 작성의 대부분의 측면은 RenderObject 작성에도 비슷하게 적용되므로, RenderBox를 고려하는 것이 추천됩니다. 가장 두드러진 차이점은 layout과 hit testing에 관한 것인데, 이는 RenderBox가 주로 다루는 부분이기 때문입니다.

 

Layout

Layout 프로토콜은 Constraints의 서브클래스로 시작합니다. Constraints 서브클래스를 어떻게 작성하는지 알고 싶다면, Constraints를 확인하세요. performLayout 메소드는 constraints를 전달받고 적용시킵니다. layout 알고리즘의 출력은 부모 레이아웃을 위해 객체의 기하학 정보를 설명하는 객체에 설정된 필드입니다. 예를 들면, RenderBox의 출력은 RenderBox.size 필드 입니다. 이 출력은 부모가 child의 layout을 호출 할 때, parentUsersSize를 true로 설정 했을 때만 read가 가능합니다.

 

어떤 객체의 레이아웃에 영향을 미치는 렌더 객채의 변화가 발생했을 때, 반드시 markNeedsLayout를 호출해야 합니다.

 

Hit Testing

Hit testing은 Layout 보다 훨씬 더 자유롭습니다. 오버라이드해야하는 메소드가 없고, hit-testing 메소드를 제공하면 됩니다.

 

hit-testing 메소드의 일반적인 동작은 RenderBox에 설명된 동작과 비슷해야합니다. 가장 큰 차이점은, 입력이 Offset일 필요가 없습니다. HitTestResult에 엔트리를 추가할 때, 다른 HitTestEntry의 서브클래스를 사용할 수 있습니다. handleEvent 메소드가 호출 될 때, HitTestResult 에 추가되는 동일한 객체가 넘겨지고, 이것은 새로운 레이아웃 프로토콜에서 어떤 좌표계를 사용했던 hit의 정확한 좌표 같은 정보를 추적하기위해 사용됩니다.

 

Adapting from one protocol to another

일반적으로, Flutter 렌더 객체의 루트는 RenderView입니다. 이 객체는 하나의 자식을 가지고, 반드시 RenderBox어야 합니다. 그러므로, 렌더 트리에 커스텀 RenderObject 서브클래스를 추가하고 싶다면 두가지 선택지가 있습니다.:  RenderView 자체를 교체하거나, 당신의 클래스를 자식으로 가지는 RenderBox를 추가할 필요가 있습니다.(보통 두번째 방법을 사용합니다.)

 

RenderBox 서브클래스는 box 프로토콜을 당신의 클래스의 프로토콜로 변환합니다.

 

특히, 이것은 hit testing의 경우 R를 오버라이드하고 hit testing을 위해 클래스에 있는 모든 메서드를 호출한다는 것을 의미합니다.

 

유사하게, 이것은 당신의 클래스에 적절한 Constraints를 만들기 위해  performLayout를 오버라이드하고 그것을 자식의 layout 메소드로 넘겨줍니다.

 

Layout interactions between render objects

일반적으로, 렌더 객체의 레이아웃은 layout 호출에서 parentUsesSize가 true로 설정되어있을 때, 오로지 자식의 레이아웃의 출력에 의존해야합니다. 게다가, parentUsersSize가 true로 설정된 경우, 부모가 자식 레이아웃을 호출해야합니다. 그렇지 않으면 자식이 레이아웃 출력을 변경할 때 부모가 알지 못하기 때문입니다.

 

렌더 객체 프로토콜이 추가적인 정보를 전달할수 있게 할 수도 있습니다. 예를 들면, enderBox 프로토콜에서 당신은 자식들의 고유한 차원가 베이스라인 기하정보를 쿼리할 수 있습니다. 그러나, 만약 부모가 자식의 정보 쿼리하고 그것을 마지막 layout 단계에서 사용한다면, 추가적인 정보의 변경이 생길 때 자식이 부모에게 markNeedsLayout를 호출해야만 합니다. 이것이 어떻게 구현되는지 코드로 알고 싶다면, RenderBox.markNeedsLayout 메소드를 확인해보세요. 이것은 RenderObject.markNeedsLayout를 오버라이드해서 만약 부모가 고유한, 베이스라인 정보를 쿼리한다면, 자식의 기하학적 정보가 변경되었을 때마다 dirty로 표시됩니다.  

 

상속 구조

구현된 타입

HitTestTarget

 

믹스인 된 타입

DiagnosticableTreeMixin

 

RenderObject를 상속하는 클래스

 

 

생성자

RenderObject()

'Flutter > API' 카테고리의 다른 글

Flutter - Element  (0) 2023.02.17
Flutter - Widget  (0) 2023.02.17
Flutter - Card  (0) 2023.02.17
Flutter - CupertinoPageScaffold  (0) 2023.02.17
Flutter - CompositedTransformFollower  (0) 2023.02.17
Comments