본문 바로가기

# 02/Flutter

[Flutter] InheritedWidget

반응형

InheritedWidget class


직관적으로 표현하고자 하는 UI component 들은 계층을 이루고 있으며, 어떤 UI를 언제 다시 그려야하는지 결정하는 메커니즘을 가지고 하나의 화면을 그려준다.


widget에서 필요한 데이터를 전달해주는 가장 간단한 방식은 부모에서 자식으로 직접 전달해주는 것이다.


그러나 애플리케이션의 UI component와 비즈니스 로직이 추가되면서 점점 복잡해짐에 따라 필연적으로 특정 데이터를 필요로 하는 widget의 개수도 하나가 아니라 여러 개로 늘어날 것이다.

이렇게 되면 부모에서 자식으로 직접 데이터를 전달해주는 방식은 비효율적이다. 

다행히도 flutter는 특별한 widget을 이용해서 특정 데이터를 계층상 아래에 있는 모든 widget에서 효율적으로 가져갈 수 있게 해주었다. 


이 특별한 widget을 InheritedWidget이라고 부른다.



class _SharedData {
String title;
int price;

_SharedData({this.title, this.price});

void updateTitle(String title) => this.title = title;
void updatePrice(int price) => this.price = price;
}



class _Data extends InheritedWidget {

final Widget child;
final _SharedData data;

_Data({this.child, this.data}): assert(child != null), assert(data != null);

@override
bool updateShouldNotify(InheritedWidget oldWidget) => false;

static _SharedData of(BuildContext context) =>
context.dependOnInheritedWidgetOfExactType<_Data>().data;
}


updateShouldNotify라는 method는 InheritedWidget이 어떠한 이유로 인해 update 되었을 때, 이 InheritedWidget에 의존하는 widget을 rebuild 할 지 결정하는 장소이다.


class _Title extends StatelessWidget {

@override
Widget build(BuildContext context) {
final sharedTitle = _Data.of(context).title;
return Text('shared title - $sharedTitle');
}
}

class _PriceDisplay extends StatelessWidget {

@override
Widget build(BuildContext context) {
final sharedPrice = _Data.of(context).price;
return Text('shared price - $sharedPrice');
}
}



BuildContext의 dependOnInheritedWidgetOfExactType method를 살펴보면 쉽게 알 수 있다. BuildContext는 위의 method를 구현하지 않았고 BuildContext의 구현체이면서 Widget의 instantiation인 Element에 구현되어 있다. 구체적으로 Element는 (Hash)Map<Type, InheritedElement>라는 구조체를 가지고 있어서 dependOnInheritedWidgetOfExactType<T>에 같이 전달되는 T라는 type으로 0(1)의 시간 복잡도로 효율적으로 데이터를 가져올 수 있다. 이 구조체는 render tree가 instantiation 될 때 부모로부터 자식으로 순서대로 전달된다.




앱이 커지고 위젯 트리가 커지면 더 복잡해지고 데이터 전달 및 액세스가 번거로울 수 있다. 


최소한 하나의 매개 변수를 허용하려면 위젯이 필요하다.


이제 우리가 물려받은 코의 후손은 빌드 메소드에서 액세스 할 수 있다.


사용자 지정 유형으로 이 메서드를 호출하여 빌드 컨텍스트에서 시작하여 트리 위로 이동한다. 해당 유형과 일치하는 위젯을 찾는다.


Theme는 사실 InheritedWidget의 한 유형이다.

Scaffold, FocusScope 모두 마찬가지


InheritedWidget은 불변이다. 이것이 우리의 이미지 자산이 최종적으로 똑똑한 이유다.


InheritedWidget의 필드 만 바꿀 수 있다.


전체 위젯을 다시 빌드한다. 


InheritedWidget은 앱의 전체 생명주기 동안 변경되지 않는다. 


그러나 무언가가 최종적이라는 사실은 재 할당 할 수 없다는 의미지 내부적으로 변경할 수 없다는 의미는 아니다.


예를 들어 값 대신 서비스 객체를 첨부할 수 있다.

서비스 개체는 자체 내부 상태를 가질 수 있다.

네트워크 호출을 시작할 수 있다.

streambuilder 구독할 수 있다.






출처 - https://blog.puppyloper.com/menus/Flutter/articles/Inherited%20widget%EC%9D%B4%20%EB%AD%90%EC%A7%80%3F

출처 - https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html



반응형