WidgetsBinding 이란?
Flutter 의 framework 와 *엔진 을 연결하는 핵심 클래스로,
- 위젯 트리의 생명 주기를 관리
- 앱의 이벤트(프레임 업데이트, 입력 이벤트, life-cycle 변화 등)를 처리
한다.
즉, Flutter 의 위젯 system 과 engine 사이의 “중재자” 역할을 수행한다.
엔진(engine)?
*Skia 그래픽 엔진과 Dart 실행 런타임을 포함하는 핵심 컴포넌트 이다.
UI 렌더링, Animation, 입력 이벤트 처리 등을 담당하는 Flutter 의 핵심 부분을 의미한다.
참고로, Fluttter 엔진은 C++ 로 작성되어 있으며, native 플랫폼과 Flutter 프레임워크를 연결하는 역할을 수행한다.
Skia 그래픽 엔진?
Google 이 개발한 오픈소스 2D 그래픽 엔진으로, Flutter 에서 그려지는 모든 UI 는 Skia 를 통해 그려진다.
그리고 Skia 는 OpenGL 을 통해 렌더링을 한다.
WIdgetBinding 의 주요 역할
1. 앱 라이프사이클 감지
앱이 background 또는 foreground 로 이동할 때 감지한다.
- WidgetsBinding.instance.addObserver : 옵저버 등록
- WidgetsBinding.instance.removeObserver : 옵저버 제거
사용할 때, with WidgetBindingObserver 를 선언해야 한다.
그리고 옵저버를 제거하지 않으면 메모리 누수가 발생하기 때문에 dispose 에서 꼭 제거해야 한다.
class MyAppLifecycleObserver extends StatefulWidget {
@override
_MyAppLifecycleObserverState createState() => _MyAppLifecycleObserverState();
}
class _MyAppLifecycleObserverState extends State<MyAppLifecycleObserver> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this); // 옵저버 등록
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
print("앱 라이프사이클 상태 변경: $state");
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this); // 옵저버 제거
super.dispose();
}
}
2. 프레임 업데이트 감지 (addPostFrameCallback)
위젯이 렌더링된 후 한 번만 실행되는 callback 함수를 추가할 수 있다.
화면이 처음 그려진 후 특정 작업을 수행할 때 유용하다.
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
print("화면이 완전히 렌더링된 후 실행됩니다!");
});
}
그리고 여기서는 initState 에서 실행할 수 없는 UI 관련 작업을 할 수 있다.
예를 들어, showDialog 같은 경우, initState 에서 실행하면 오류가 발생하는데 addPostFrameCallback 에서 실행하면 정상적으로 동작한다.
3. 입력 이벤트 처리 (handlePointerEvent)
사용자의 터치, 키보드 입력과 같은 이벤트를 처리할 때 사용한다.
사실 대부분 Flutter 내부에서 자동 처리되지만, 커스텀 입력 이벤트 처리가 필요할 경우에 활용하면 좋다.
WidgetsBinding.instance.platformDispatcher.onPointerDataPacket = (data) {
print("사용자가 터치 이벤트를 발생시킴: $data");
};
WidgetBinding.instance 란?
WidgetBinding 은 싱글톤 객체로, Flutter 앱에서 하나만 존재해야 한다.
그래서 WidgetBinding.instance 를 사용하면 현재 실행 중인 WidgetsBinding의 인스턴스를 가져올 수 있다.
주의할 점으로, WidgetsBinding.instance 를 호출하려면 반드시 runApp(); 이 실행된 이후여야 하기 때문에
main() 함수에서 WidgetsFlutterBinding.ensureInitialized(); 를 사용하여 WidgetsBinding 이 초기화 되었는지 보장해야 한다.
void main() {
WidgetsFlutterBinding.ensureInitialized(); // WidgetsBinding 초기화
runApp(MyApp());
}