티스토리 뷰
조상으로부터 Provider를 얻고 해당 값을 builder에 전달합니다.
Consumer 위젯은 특별한 작업을 하지 않습니다. 단지 새로운 위젯에서 Provider.of를 호출하고 빌드 구현을 builder에 위임합니다.
builder는 null이 될 수 없으며 제공된 값이 변경될 때 여러 번 호출될 수 있습니다.
Consumer 위젯의 두 가지 주요 목적은 다음과 같습니다:
- 해당 제공자의 후손이 아닌 BuildContext를 가지고 있을 때 제공자의 값을 얻을 수 있게 합니다.
- 더 세밀한 리빌드를 통해 성능을 최적화합니다.
해당 제공자의 후손이 아닌 BuildContext를 가지고 있을 때 제공자의 값을 얻기
이 시나리오는 제공자를 생성하는 위젯이 그 제공자의 소비자이기도 할 때 주로 발생합니다. 예를 들어:
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => Foo(),
child: Text(Provider.of<Foo>(context).value),
);
}
이 예제는 Provider.of가 제공자의 조상인 BuildContext로 호출되기 때문에 ProviderNotFoundException을 발생시킵니다.
대신, Consumer 위젯을 사용하면 자체 BuildContext로 Provider.of를 호출할 수 있습니다.
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => Foo(),
child: Consumer<Foo>(
builder: (_, foo, __) => Text(foo.value),
),
);
}
이 코드는 ProviderNotFoundException을 발생시키지 않고 Text를 올바르게 빌드합니다. 또한 foo의 값이 변경될 때마다 Text를 업데이트합니다.
더 세밀한 리빌드를 통해 성능을 최적화하기
listen: false를 Provider.of에 전달되지 않으면, Provider.of에 전달된 BuildContext와 연관된 위젯은 값이 변경될 때마다 리빌드됩니다. 이는 예상된 동작이지만 때로는 더 많은 위젯이 리빌드될 수 있습니다. 예를 들어:
@override
Widget build(BuildContext context) {
return FooWidget(
child: BarWidget(
bar: Provider.of<Bar>(context),
),
);
}
위 코드에서는 BarWidget만 Provider.of로 반환된 값에 의존합니다. 그러나 Bar가 변경되면 BarWidget과 FooWidget 모두 리빌드됩니다.
이상적으로는 BarWidget만 리빌드되어야 합니다. 이를 위해 Consumer를 사용할 수 있습니다.
@override
Widget build(BuildContext context) {
return FooWidget(
child: Consumer<Bar>(
builder: (_, bar, __) => BarWidget(bar: bar),
),
);
}
이 상황에서는 Bar가 업데이트될 때 BarWidget만 리빌드됩니다.
하지만 FooWidget이 제공자에 의존하고 BarWidget은 제공자에 의존하지 않는 경우는 어떻게 될까요? 예를 들어:
@override
Widget build(BuildContext context) {
return FooWidget(
foo: Provider.of<Foo>(context),
child: BarWidget(),
);
}
Consumer를 사용하여 이 시나리오를 선택적 child 인수를 사용하여 처리할 수 있습니다:
@override
Widget build(BuildContext context) {
return Consumer<Foo>(
builder: (_, foo, child) => FooWidget(foo: foo, child: child),
child: BarWidget(),
);
}
이 예제에서는 BarWidget이 builder 외부에서 생성됩니다. 그런 다음 BarWidget 인스턴스가 마지막 매개변수로 builder에 전달됩니다.
이는 builder가 새로운 값으로 다시 호출될 때 새로운 BarWidget 인스턴스가 생성되지 않음을 의미합니다. 이를 통해 Flutter는 BarWidget을 리빌드할 필요가 없음을 알게 됩니다. 따라서 이러한 구성에서는 Foo가 변경될 때 FooWidget만 리빌드됩니다.
참고
Consumer 위젯은 MultiProvider 내에서도 사용할 수 있습니다. 이를 위해 builder에 전달된 child를 반환해야 합니다.
MultiProvider(
providers: [
Provider(create: (_) => Foo()),
Consumer<Foo>(
builder: (context, foo, child) =>
Provider.value(value: foo.bar, child: child),
)
],
);
참조:
- Selector: 업데이트를 필터링할 수 있는 Consumer.
생성자
- Consumer({Key? key, required Widget builder(BuildContext context, T value, Widget? child), Widget? child}) : Provider를 소비합니다.
속성
- builder → Widget Function(BuildContext context, T value, Widget? child): Provider의 값을 기반으로 위젯 트리를 빌드합니다.
- hashCode → int: 객체의 해시 코드입니다.
- key → Key?: 트리에서 하나의 위젯이 다른 위젯으로 교체되는 방식을 제어합니다.
- runtimeType → Type: 객체의 런타임 유형을 나타냅니다.
메서드
- build(BuildContext context) → Widget: 이 위젯이 표현하는 사용자 인터페이스의 일부를 설명합니다.
- buildWithChild(BuildContext context, Widget? child) → Widget: 추가 자식 매개변수를 받는 빌드 메서드입니다.
- createElement() → SingleChildStatelessElement: 이 위젯의 위치를 관리할 StatelessElement를 생성합니다.
- debugDescribeChildren() → List: 이 노드의 자식을 설명하는 DiagnosticsNode 객체 목록을 반환합니다.
- debugFillProperties(DiagnosticPropertiesBuilder properties) → void: 노드와 관련된 추가 속성을 추가합니다.
- noSuchMethod(Invocation invocation) → dynamic: 존재하지 않는 메서드나 속성에 접근할 때 호출됩니다.
- toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode: 디버깅 도구와 DiagnosticsNode.toStringDeep에서 사용하는 객체의 디버그 표현을 반환합니다.
- toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) → String: 이 객체의 문자열 표현입니다.
- toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String: 이 노드와 그 자손의 문자열 표현을 반환합니다.
- toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String: 객체의 한 줄 상세 설명을 반환합니다.
- toStringShort() → String: 이 위젯의 짧은 텍스트 설명입니다.
연산자
- operator ==(Object other) → bool: 동등 연산자입니다.
'Flutter > 상태 관리' 카테고리의 다른 글
플러터] Provider 패키지 README.md (0) | 2024.07.02 |
---|---|
플러터] Provider - Selector<A, S> 클래스 (0) | 2024.07.02 |
플러터] Provider - ChangeNotifierProxyProvider 클래스 (0) | 2024.07.01 |
플러터] Provider - ChangeNotifierProvider 클래스 (0) | 2024.07.01 |
플러터] Provider에 등록된 상태에 접근하는 방법들 (0) | 2023.07.13 |