-
[flutter] _overlay == null"An OverlayEntry must first be removed from the Overlay before dispose is called."Flutter 오류 2025. 1. 1. 20:19
이 에러는 Flutter의 Overlay와 관련된 문제로, 특정 위젯이 제거되기 전에 OverlayEntry가 제대로 제거되지 않았을 때 발생한다.
에러 원문 분석
- Assertion failed
- Flutter는 위젯 상태를 관리할 때 특정 조건을 확인하는 assertion을 사용한다.
- 여기서 _overlay == null이라는 조건이 실패했다는 뜻이다.
- An OverlayEntry must first be removed from the Overlay before dispose is called.
- OverlayEntry는 Flutter에서 팝업, 툴팁, 드롭다운 등과 같은 UI 요소를 관리하기 위해 사용된다.
- 이 에러는 OverlayEntry를 Overlay에서 제거(remove())하지 않고, dispose()를 호출하여 메모리에서 제거하려고 할 때 발생한다.
문제 발생 상황
이 에러는 보통 다음과 같은 상황에서 발생한다:
- OverlayEntry를 추가했지만 제거하지 않음
- Overlay.of(context).insert(overlayEntry)로 추가한 후, overlayEntry.remove()를 호출하지 않고 위젯이 파괴(dispose)되었을 때.
- OverlayEntry의 수명 관리 문제
- OverlayEntry를 사용하는 위젯(예: Dropdown, Tooltip, CustomPopup)이 위젯 트리에서 제거되기 전에 remove()가 호출되지 않은 경우.
- 비동기 작업
- Future, Stream, 또는 다른 비동기 작업 중 OverlayEntry를 추가한 뒤 작업 완료 전에 위젯이 dispose된 경우.
해결 방법
이 문제를 해결하려면 OverlayEntry를 dispose 전에 명시적으로 제거해야 한다. 아래의 단계를 따른다:
1. OverlayEntry를 명시적으로 관리
OverlayEntry를 변수로 저장하고, 제거 시 remove()를 호출한다:
late OverlayEntry overlayEntry; void showOverlay(BuildContext context) { overlayEntry = OverlayEntry( builder: (context) => Positioned( top: 100, left: 100, child: Material( child: Text('Hello, Overlay!'), ), ), ); Overlay.of(context)?.insert(overlayEntry); } void hideOverlay() { overlayEntry.remove(); }
2. dispose에서 제거 확인
위젯이 dispose될 때 OverlayEntry를 제거하도록 만든다:
@override void dispose() { if (overlayEntry.mounted) { overlayEntry.remove(); // OverlayEntry가 남아있는 경우 제거 } super.dispose(); }
3. 비동기 작업이 중단될 경우 대비
비동기 작업 중 위젯이 dispose될 가능성을 처리하려면 mounted 여부를 확인한다:
Future<void> performAsyncTask(BuildContext context) async { overlayEntry = OverlayEntry( builder: (context) => Positioned( top: 100, left: 100, child: Material( child: Text('Loading...'), ), ), ); Overlay.of(context)?.insert(overlayEntry); await Future.delayed(Duration(seconds: 2)); // 예제 비동기 작업 if (mounted) { overlayEntry.remove(); } }
요약
- OverlayEntry를 추가했으면 반드시 명시적으로 제거해야 한다.
- dispose 전에 OverlayEntry.remove()를 호출하여 메모리 누수를 방지한다.
- 비동기 작업에서 mounted 여부를 확인해 위젯 상태와 동기화한다.
이렇게 하면 해당 에러를 방지할 수 있다.
메모리관리 측면에서 중요하다!
'Flutter 오류' 카테고리의 다른 글
- Assertion failed