Navigator.of(context).push(); // 화면 전환
Fluttertoast.showToast(msg: "message"); // 토스트 메시지
Q. 위 두 함수는 UI와 관련이 있지만 왜
build
과정의 영향을 받고 안 받고의 차이가 있을까?
MVVM
패턴으로 앱을 구현해보는 중에 든 궁금증이다.
도대체 Buildcontext
가 뭐길래 에러가 발생하는걸까?
이전 게시글에서 MVVM 패턴과 상태관리에 대해 다루면서 BuildContext
개념을 언급하였는데, 관련해서 추가 학습이 필요한 것 같으니 정리해보자.
BuildContext
는 위젯 트리 내에서의 위치정보를 가지고 있으며, 위젯 트리 내 특정 부분을 탐색하거나 부모 위젯의 데이터를 가져오는 데 사용된다.
사용한 현재 context
를 기준으로 위로 올라가면서 가장 가까운 위젯 또는 객체를 찾아 반환한다.
Provider.of<T>(context); // Provider
우리가 Provider
에서 주입된 인스턴스를 사용하기 위해 작성했던 위 코드도, 해당 context
기준 주입된 가장 가까운 T
타입의 객체를 찾기 위해서 사용되는 코드이다.
Navigator.of(context).push(); // Navigator
이어서 Buildcontext
를 사용하여 할 수 있는 대표적인 작업이 바로 Navigator.of(context)
를 사용하여 화면을 전환하는 것이다.
context
를 기준으로 가장 가까은 Navigator
를 찾고, Navigator
에서 관리되는 Stack
에 새로운 화면을 생성한다.
여기서 Navigator
위젯은 최상위 MaterialApp
이 생성될 때 기본적으로 1개가 같이 생성되며, 별도로 Stack
관리가 필요할 때 추가로 생성할 수 있다.
context
가 새로 생성된 위젯의 위치 정보를 가지는 시점은 위젯의 build
과정이 전부 진행되고 난 후이기 때문에 build
이후 context
를 사용해야 한다.
그렇기에 WidgetsBinding.instance.addPostFrameCallback
과 같은 함수를 이용해서 프레임 렌더링이 끝나고 난 후 context
를 사용하는 작업을 실행할 수 있도록 하는 것이다.
if (context.mounted) { // context 유효성 검사
...
}
같은 이유로, 비동기 함수는 메인 스레드가 아닌 event loop
에서 동작하기 때문에, 비동기 함수 내에서 context
를 사용할 때에는 위와 같이 mounted
프로퍼티를 사용하여 해당 context
가 위젯 트리에 연결 되어있는지 검사 후 사용해야 한다.
Navigator.of(context).push(); // 화면 전환
Fluttertoast.showToast(msg: "message"); // 토스트 메시지
Q. 위 두 함수는 UI와 관련이 있지만 왜
build
과정의 영향을 받고 안 받고의 차이가 있을까?
그러면 이제 내가 가지고 있었던 위 궁금증도 간단하게 해결이 된다.
A. 화면 전환 함수는
context
를 사용하기 대문에 실행 시점이build
과정의 영향을 받지만, 토스트 메시지를 띄우는 함수는context
를 사용하지 않기 때문에build
과정과는 무관하다.