티스토리 뷰
Dart & Flutter/궁금했던 것, 몰랐던 것
Flutter에서 didUpdateWidget 메서드가 호출될 때 oldWidget.a와 widget.a 값이 둘 다 변경 후의 값을 가지는 이유
낭초비 2025. 3. 18. 21:11반응형
배경 이해
- didUpdateWidget의 역할
didUpdateWidget은 부모 위젯이 다시 빌드되면서 자식 위젯에 새로운 데이터(예: a 리스트)를 전달할 때 호출됩니다. 이 메서드는 이전 위젯(oldWidget)과 현재 위젯(widget)을 비교하여 필요한 업데이트를 처리할 수 있게 해줍니다. - setState와 위젯 트리 업데이트
부모 위젯에서 setState를 호출하면 상태 변수(a)가 변경되고, Flutter는 부모 위젯의 build 메서드를 다시 실행합니다. 이 과정에서 자식 위젯도 새로운 인수(변경된 a)를 받게 됩니다.
문제 상황 분석
당신의 코드에서:
- 부모 위젯은 List<bool> a를 상태로 가지고 있고, setState를 통해 a의 값을 변경합니다.
- 자식 위젯은 부모로부터 a를 인수로 받아 사용합니다.
- didUpdateWidget에서 oldWidget.a와 widget.a를 확인했더니 둘 다 변경 후의 값(예: [true, false])을 가리키고 있다는 점이 의문입니다.
왜 oldWidget.a와 widget.a가 같은 값을 가질까?
이는 **Dart의 객체 참조(reference)**와 Flutter의 위젯 업데이트 타이밍 때문입니다.
- List<bool> a는 참조 타입
Dart에서 리스트(List)는 참조 타입입니다. 부모 위젯에서 a를 정의하고 자식 위젯에 전달할 때, 실제로 리스트의 복사본이 전달되는 것이 아니라 **참조(레퍼런스)**가 전달됩니다. 따라서 부모 위젯에서 setState를 호출해 a의 내용을 수정하면(예: a[0] = true), 해당 리스트 객체 자체가 변경됩니다. - oldWidget의 생성 시점
didUpdateWidget이 호출될 때 oldWidget은 이전 빌드 시점의 위젯 인스턴스를 나타냅니다. 하지만 oldWidget.a는 여전히 부모 위젯의 a 리스트에 대한 참조를 가리킵니다. 부모에서 setState로 a의 내용을 변경하면, 그 참조가 가리키는 데이터가 바뀌기 때문에 oldWidget.a도 변경된 값을 반영하게 됩니다. - widget.a와 동일성
마찬가지로 widget.a는 새로 빌드된 위젯에 전달된 a의 참조입니다. 부모 위젯의 build 메서드가 호출될 때 a를 자식에게 전달하므로, widget.a 역시 동일한 리스트 객체를 가리킵니다. 결과적으로 oldWidget.a와 widget.a는 같은 객체를 참조하고, 그 객체의 내용은 이미 변경된 상태입니다.
해결 방법
만약 didUpdateWidget에서 이전 값(oldWidget.a)과 새 값(widget.a)을 제대로 비교하고 싶다면, 리스트를 깊은 복사(deep copy) 해서 전달하거나, 리스트 자체를 새로 생성해야 합니다.
1. 깊은 복사 사용
부모 위젯에서 자식 위젯에 a를 전달할 때 복사본을 제공:
ChildWidget(a: List.from(a)), // 새로운 리스트 인스턴스 생성
이렇게 하면 oldWidget.a와 widget.a가 서로 다른 객체를 가리키므로, didUpdateWidget에서 이전 값과 새 값을 정확히 비교할 수 있습니다.
2. 상태를 자식 위젯에서 관리
또는 a를 자식 위젯 내부에서 상태로 관리하고, 부모로부터 변경 사항을 받을 때마다 업데이트하도록 설계할 수도 있습니다.
결론
oldWidget.a와 widget.a가 동일한 값을 가지는 이유는 둘 다 동일한 List<bool> 객체를 참조하고 있고, 부모에서 setState로 리스트 내용을 변경했기 때문입니다. 이를 피하려면 리스트를 복사하거나 설계를 조정해야 합니다. 질문이 더 있으면 말씀해주세요!
반응형
'Dart & Flutter > 궁금했던 것, 몰랐던 것' 카테고리의 다른 글
부모 위젯 상에서 자식 위젯에 정의된 메서드 호출 하는 방법 (0) | 2024.07.29 |
---|---|
Riverpod 을 자동생성기로 생성할 때 State Provider 는 지원하지 않음 (0) | 2024.07.26 |
TextField 영역 바깥을 터치시 keyboard 숨기기 (0) | 2024.01.17 |
system UI (status bar/navigation bar) 안 보이게 만들기 (0) | 2023.10.25 |
팝업창 위치 조정 (0) | 2023.10.16 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- UI
- 다트
- 디자인
- 한빛미디어
- 앱개발
- 크롬
- IOS
- addPostFrameCallback
- Bluetooth
- TextFormField
- 인사이트
- 에러
- UX
- error
- Flutter
- 이미지
- TextField
- Chrome
- plugin
- 앱
- BLE
- 문제 해결
- firebase
- DART
- hide
- 플러터
- position
- SizedBox
- Syncfusion
- 앱 프로그래밍
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
글 보관함