TL; DR
updateShouldNotify 메서드 내에서 무거운 계산을 사용하지 말고 위젯을 만들 때 new 대신 const 를 사용하십시오.
우선, 우리는 Widget, Element, Render 객체가 무엇인지 이해해야합니다.
- 렌더 객체는 실제로 화면에 렌더링되는 것입니다. 그들은 가변적 이며 페인팅 및 레이아웃 로직을 포함합니다. 렌더 트리는 웹의 DOM (Document Object Model)과 매우 유사하며이 트리에서 렌더 객체를 DOM 노드로 볼 수 있습니다.
- 위젯 -렌더링해야하는 항목에 대한 설명입니다. 그들은 불변 하고 저렴합니다. 따라서 위젯이 "무엇입니까?"(선언적 접근 방식) 질문에 대답하면 Render 객체는 "어떻게?"(명령 적 접근 방식) 질문에 대답합니다. 웹의 비유는 "가상 DOM"입니다.
- Element / BuildContext- 위젯 과 렌더 객체 간의 프록시 입니다. 여기에는 트리 *에서 위젯의 위치에 대한 정보와 해당 위젯이 변경 될 때 Render 객체를 업데이트하는 방법이 포함되어 있습니다.
이제 InheritedWidget 및 BuildContext의 메서드 inheritFromWidgetOfExactType을 살펴볼 준비가되었습니다 .
예를 들어, InheritedWidget에 대한 Flutter의 문서에서이 예제를 고려하는 것이 좋습니다.
class FrogColor extends InheritedWidget {
const FrogColor({
Key key,
@required this.color,
@required Widget child,
}) : assert(color != null),
assert(child != null),
super(key: key, child: child);
final Color color;
static FrogColor of(BuildContext context) {
return context.inheritFromWidgetOfExactType(FrogColor);
}
@override
bool updateShouldNotify(FrogColor old) {
return color != old.color;
}
}
InheritedWidget-우리의 경우 하나의 중요한 메소드 인 updateShouldNotify 를 구현하는 위젯입니다 .
updateShouldNotify- 하나의 매개 변수 oldWidget 을 받아들이고 부울 값 (true 또는 false)을 반환 하는 함수입니다 .
다른 위젯과 마찬가지로 InheritedWidget 에는 해당하는 Element 객체가 있습니다. 그것은이다 InheritedElement . InheritedElement 는 새로운 위젯을 만들 때마다 위젯에서 updateShouldNotify 를 호출 합니다 (조상에서 setState 를 호출 합니다). updateShouldNotify 때 가 true를 반환 InheritedElement 는 종속성 (?)을 반복 하고 didChangeDependencies 를 호출 합니다.
InheritedElement가 가져 오는 위치 종속성을 습니까? 여기에서 inheritFromWidgetOfExactType 메소드를 살펴 보겠습니다 .
inheritFromWidgetOfExactType -BuildContext 및 모든 요소에 정의 된이 메소드
는 BuildContext 인터페이스를 구현합니다 (Element == BuildContext). 따라서 모든 요소에는이 방법이 있습니다.
inheritFromWidgetOfExactType의 코드를 살펴 보겠습니다.
final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[targetType];
if (ancestor != null) {
assert(ancestor is InheritedElement);
return inheritFromElement(ancestor, aspect: aspect);
}
여기서 우리는 _inheritedWidgets 에서 조상을 찾으려고합니다. 매핑 된 합니다. 조상을 찾으면 inheritFromElement 를 호출 합니다 .
inheritFromElement 코드 :
InheritedWidget inheritFromElement(InheritedElement ancestor, { Object aspect }) {
assert(ancestor != null);
_dependencies ??= HashSet<InheritedElement>();
_dependencies.add(ancestor);
ancestor.updateDependencies(this, aspect);
return ancestor.widget;
}
- 현재 요소 (_dependencies.add (ancestor))의 종속성으로 ancestor를 추가합니다.
- 현재 요소를 조상의 종속성에 추가합니다 (ancestor.updateDependencies (this, aspect)).
- inheritFromWidgetOfExactType의 결과로 조상의 위젯을 반환합니다 (ancestor.widget 반환).
이제 InheritedElement가 종속성을 얻는 위치를 알았습니다.
이제 didChangeDependencies 메소드를 살펴 보겠습니다 . 모든 요소에는 다음 방법이 있습니다.
void didChangeDependencies() {
assert(_active); // otherwise markNeedsBuild is a no-op
assert(_debugCheckOwnerBuildTargetExists('didChangeDependencies'));
markNeedsBuild();
}
우리가 볼 수 있듯이이 메서드는 요소를 더티 로 표시 하고이 요소는 다음 프레임에서 다시 작성되어야합니다. Rebuild 는 코어에 해당하는 위젯 요소에서 메서드 빌드 를 호출하는 것을 의미합니다 .
그러나 "InheritedWidget을 다시 빌드 할 때 전체 하위 트리가 다시 빌드됩니까?"는 어떻습니까? 여기서 우리는 위젯은 불변이며 새 위젯을 생성하면 Flutter가 하위 트리를 다시 빌드한다는 것을 기억해야합니다. 어떻게 고칠 수 있습니까?
- 손으로 위젯 캐시 (수동)
- 사용 CONST CONST이 때문에 유일하게 하나 개의 인스턴스 생성 값 / 클래스를