티스토리 뷰
가장 가까운 조상 제공자(ancestor provider)로부터 타입 T의 값을 얻습니다.
이 메서드는 watch의 반대입니다.
값이 변경될 때 위젯을 재빌드하지 않으며 StatelessWidget.build와 State.build 내부에서 호출해서는 안 됩니다.
반면, 이러한 메서드 외부에서는 자유롭게 호출할 수 있습니다.
이 기준과 호환되지 않는 경우, Provider.of(context, listen: false)를 사용하는 것을 고려하세요.
이 메서드는 동일한 작업을 수행하지만 이러한 추가 제한 사항 없이 사용할 수 있습니다 (하지만 안전하지는 않습니다).
[X] 값이 이벤트에만 사용되는 경우 build 내부에서 read를 호출하지 마세요:
Widget build(BuildContext context) {
// counter는 RaisedButton의 onPressed에서만 사용됩니다.
final counter = context.read<Counter>();
return RaisedButton(
onPressed: () => counter.increment(),
);
}
이 코드 자체는 버그가 없지만, 이것은 안티패턴입니다. 위젯을 리팩토링한 후 counter를 다른 용도로 사용하게 되었지만 read를 watch로 변경하는 것을 잊어버리면 쉽게 버그가 발생할 수 있습니다.
[O] 이벤트 핸들러 내부에서 read를 호출하는 것을 고려하세요:
Widget build(BuildContext context) {
return RaisedButton(
onPressed: () {
// 이전 솔루션만큼 성능이 좋지만 리팩토링에 강합니다.
context.read<Counter>().increment(),
},
);
}
이것은 이전의 안티패턴과 동일한 효율성을 가지지만, 깨지기 쉬운 단점이 없습니다.
[X] 변경되지 않는 값을 가진 위젯을 만들기 위해 read를 사용하지 마세요:
Widget build(BuildContext context) {
// 변경되지 않는 값을 사용하기 때문에 read를 사용합니다.
final model = context.read<Model>();
return Text('${model.valueThatNeverChanges}');
}
다른 것이 변경될 때 위젯을 재빌드하지 않는다는 아이디어는 좋지만, 이것은 read로 수행해서는 안 됩니다. 최적화를 위해 read에 의존하는 것은 매우 불안정하며 구현 세부 사항에 의존합니다.
[O] 원하지 않는 재빌드를 필터링하기 위해 select를 사용하는 것을 고려하세요:
Widget build(BuildContext context) {
// 사용된 값만 수신하기 위해 select를 사용합니다.
final valueThatNeverChanges = context.select((Model model) => model.valueThatNeverChanges);
return Text('$valueThatNeverChanges');
}
read보다 더 장황하지만, select를 사용하는 것이 훨씬 안전합니다. Model의 구현 세부 사항에 의존하지 않으며, UI가 새로 고쳐지지 않는 버그가 발생할 가능성이 없습니다.
다른 객체에 의존하는 객체를 단순화하기 위해 read를 사용하기
이 메서드는 객체에 자유롭게 전달될 수 있으며, BuildContext에 대한 참조 없이 제공자를 읽을 수 있습니다.
class Model {
Model(this.context);
final BuildContext context;
void method() {
print(Provider.of<Whatever>(context));
}
}
// ...
Provider(
create: (context) => Model(context),
child: ...,
)
대신 다음과 같이 작성하는 것을 선호합니다:
class Model {
Model(this.read);
// `Locator`는 `read`의 타입과 일치하는 typedef입니다.
final Locator read;
void method() {
print(read<Whatever>());
}
}
// ...
Provider(
create: (context) => Model(context.read),
child: ...,
)
두 코드 스니펫은 동일하게 동작합니다. 그러나 두 번째 스니펫에서는 Model이 Flutter/BuildContext/provider에 의존하지 않습니다.
참고
- WatchContext와 그 watch 메서드, read와 유사하지만 얻은 값이 변경될 때 위젯 트리를 재빌드합니다.
- Locator, read를 객체에 전달하기 쉽게 만드는 typedef입니다.
구현
T read<T>() {
return Provider.of<T>(this, listen: false);
}
'Flutter > 상태 관리' 카테고리의 다른 글
플러터 ChangeNotifierProvider 완전 정복 (1) | 2024.07.03 |
---|---|
플러터] Provider - Provider 클래스 (0) | 2024.07.02 |
플러터] Provider - Provider.of 정적 메서드 (0) | 2024.07.02 |
플러터] 상태 관리 (State management) (0) | 2024.07.02 |
플러터] Provider 패키지 README.md (0) | 2024.07.02 |