BuildContext 에 대해서 몇가지 느낀점을 정리해보았다.
- 위젯트리에서 현재 위젯의 위치를 알수있는 정보
- BuildContext는 위젯의 정보를 가짐
- build 메소드에 의해 전해지는 context는 부모 위젯까지의 정보만 가짐
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyPage(),
);
}
}
class MyPage extends StatelessWidget {
const MyPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) { // 여기서 사용하는 context는 Mypage에 대한것임
return Scaffold(
appBar: AppBar(
title: const Text('SnackBar'),
centerTitle: true,
),
body: Center(
child: ElevatedButton(
onPressed: () {
print('Show me is clicked');
},
child: const Text('Show me'),
),
),
);
}
}
여기서 Scaffold 내부에서 사용하는 context가 누구의 것인지 확인하는 코드를 추가해보자
상식적으로는 Scaffold 내부의 context는 Scaffold 의 것이어야 하는데, 현실은 그렇지 않다.
아래 코드처럼 MyPage 부분을 수정하였다.
class MyPage extends StatelessWidget {
const MyPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('SnackBar'),
centerTitle: true,
),
body: Center(
child: ElevatedButton(
onPressed: () {
print('Show me is clicked');
Scaffold.of(context) // 이부분을 추가해서 발생하는 오류 메시지 확인
.showSnackBar(const SnackBar(content: Text('Clicked SnackBar')));
},
child: const Text('Show me'),
),
),
);
}
}
"Show me" 버튼을 클릭하면 오류가 발생한다.
오류의 내용 중, "Scaffold.of() called with a context that does not contain a Scaffold." 라는 메시지와 "The context used was: MyPage" 메시지를 주목해보면 Scaffold 내부에서 호출된 스낵바에서 참조하는 Scaffold 는 없으며 사용된 context는 MyPage 의 것임을 알 수 있다.
해당 문제를 해결하는 방법은 2가지가 있으며 하나는 Builder를 사용해서 context 를 다시 만드는 방법과 새로운 위젯으로 분리하는 방법이 있다.
1. 먼저 Builder 를 사용하는 경우, 새로운 context 를 생성할 수 있다.
class MyPage extends StatelessWidget {
const MyPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('SnackBar'),
centerTitle: true,
),
body: Builder( // Builder 로 감싸는 경우
builder: (context) {
return Center(
child: ElevatedButton(
onPressed: () {
print('Show me is clicked');
Scaffold.of(context)
.showSnackBar(const SnackBar(content: Text('Clicked SnackBar')));
},
child: const Text('Show me'),
),
);
}
),
);
}
}
여기에서 위젯트리의 변경사항을 확인해 보면 아래 그림과 같다
2. 새로운 위젯으로 분리하는 방법이 있다.
class MyPage extends StatelessWidget {
const MyPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('SnackBar'),
centerTitle: true,
),
body: MySnackBar(), // 새로운 위젯을 만들어서 context 를 만드는 효과 생김
);
}
}
class MySnackBar extends StatelessWidget {
const MySnackBar({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: ElevatedButton(
onPressed: () {
print('MySnackBar is clicked');
Scaffold.of(context)
.showSnackBar(const SnackBar(content: Text('Clicked MySnackBar')));
},
child: const Text('MySnackBar'),
),
);
}
}
이상으로 우리가 무의식적으로 사용하던 context 가 위젯들 사이에서 어떤 역할을 하는지 간단히 알아보았다.
[참고자료] 코딩셰프 -
[https://www.youtube.com/watch?v=o-HpnWhI70U&list=PLQt_pzi-LLfpcRFhWMywTePfZ2aPapvyl&index=18]
'Flutter > 06 Basic' 카테고리의 다른 글
[Flutter] 안드로이드 스튜디오 설정 - 자동완성 기능 추가 (0) | 2022.08.18 |
---|---|
[Flutter] Firestore 구조 알아보기 (0) | 2022.08.12 |
[Flutter] Basic - key (0) | 2022.07.08 |
[Flutter] Basic - ScaffoldMessenger (0) | 2022.04.14 |
[Flutter] Basic - Navigator (0) | 2022.04.14 |