`use_build_context_synchronously` 린트 규칙: 비동기 간격에서의 BuildContext 사용
use_build_context_synchronously 린트 규칙: 비동기 간격에서의 BuildContext 사용
use_build_context_synchronously는 비동기 간격(asynchronous gap)을 지나서 BuildContext를 사용할 때 Dart 분석기가 알려주는 린트 규칙이에요. Flutter 위젯 코드에서 매우 흔하게 접하는 실수를 막아 주는 규칙이에요.
본문
설명
비동기 간격을 지나서 BuildContext를 사용하지 마세요. BuildContext를 나중에 쓰려고 저장해 두면 진단하기 어려운 크래시로 쉽게 이어질 수 있어요. 비동기 간격은 BuildContext를 슬쩍 저장해 두는 셈이라서, 코드를 쓸 때 가장 놓치기 쉬운 부분 중 하나예요.
BuildContext를 사용할 때는 비동기 간격 이후에 mounted 속성을 확인해야 해요. 확인할 대상은 BuildContext에 어떻게 접근했는지에 따라 달라져요.
State의context속성을 사용할 때는State의mounted속성을 확인해야 해요.- 다른
BuildContext인스턴스(지역 변수나 함수 인자 같은 것)를 사용할 때는BuildContext의mounted속성을 확인해야 해요.
BAD:
void onButtonTapped(BuildContext context) async {
await Future.delayed(const Duration(seconds: 1));
Navigator.of(context).pop();
}
await로 비동기 간격을 지난 뒤에 context를 쓰고 있어요. 이 사이에 위젯이 화면에서 사라지면 크래시가 날 수 있어요.
GOOD:
void onButtonTapped(BuildContext context) {
Navigator.of(context).pop();
}
비동기 간격이 없으면 그냥 사용해도 돼요.
void onButtonTapped(BuildContext context) async {
await Future.delayed(const Duration(seconds: 1));
if (!context.mounted) return;
Navigator.of(context).pop();
}
비동기 이후에 context.mounted를 확인한 뒤에만 사용해요. BuildContext의 mounted 속성을 쓰는 예시예요.
abstract class MyState extends State<MyWidget> {
void foo() async {
await Future.delayed(const Duration(seconds: 1));
if (!mounted) return; // Checks `this.mounted`, not `context.mounted`.
Navigator.of(context).pop();
}
}
State 안이라면 this.mounted(간단히 mounted)를 확인해요. 주석에도 있듯이 여기서는 context.mounted가 아니라 this.mounted를 검사해요.
활성화하기
use_build_context_synchronously 규칙을 켜려면 analysis_options.yaml 파일의 linter > rules에 use_build_context_synchronously를 추가해요.
linter:
rules:
- use_build_context_synchronously
YAML 맵 문법을 쓴다면 linter > rules 아래에 use_build_context_synchronously: true를 넣으면 돼요.
linter:
rules:
use_build_context_synchronously: true