1. StatefulWidget
StatelessWidget → only UI
StatefulWidget → UI + 비즈니스 로직(상태 + 행위)
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("MyApp build..."); // MyApp build 실행 시 실행
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget { // 알트 엔터로 statefulWidget으로 변경 가능
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int num = 1;
@override
Widget build(BuildContext context) {
print("HomePage build..."); // HomePage build 실행 시 실행
return Scaffold(
body: Column(
children: [
Expanded(
child: Center(
child: Container(
child: Text("$num", style: TextStyle(fontSize: 30)),
),
),
),
Expanded(
child: Center(
child: Container(
child: ElevatedButton(onPressed: () {
num++;
setState(() {});
print("num : $num");
},
child: Icon(Icons.add),
),
),
),
),
],
),
);
}
}

- 플러스 버튼을 누르면 위의 숫자가 올라가는 코드입니다.
- StatelessWidget 이었던 HomePage를 StatefulWidget 위젯으로 바꾸면 상태(숫자) 변화를 화면에 반영시킬 수 있습니다.
- setState(() {})
- 변경된 상태를 반영해서 다시 그림을 그립니다. - rebuild
- 위 코드의 문제점
- 상태 변경으로 리빌드 될 때 Scaffold, Column, ElevatedButton 등 빌드 안 해도 되는 위젯까지 다시 빌드 됩니다.
- Text 위젯만 바꾸려면? → context분리가 필요합니다.
2. Middle Widget으로 BuildContext 분리
// class MyApp 은 위와 동일
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("HomePage build...");
return Scaffold(
body: MiddleWidget(), // Middle Widget으로 분리
);
}
}
class MiddleWidget extends StatefulWidget {
const MiddleWidget({
super.key,
});
@override
State<MiddleWidget> createState() => _MiddleWidgetState();
}
class _MiddleWidgetState extends State<MiddleWidget> {
// 1. 상태
int num = 1;
// 2. 행위
void increase() {
num++;
setState(() {});
}
@override
Widget build(BuildContext context) {
print("MiddleWidget build...");
return Column(
children: [
Expanded(
child: Top(num),
),
Expanded(
child: Bottom(increase), // increase()가 아니다. 변수를 넘기는 것
),
],
);
}
}
class Bottom extends StatelessWidget {
Function increase; // 함수는 타입이 Function
Bottom(this.increase);
@override
Widget build(BuildContext context) {
print("Bottom build...");
return Center(
child: Container(
child: ElevatedButton(onPressed: (){
increase(); // 받은 함수를 실행
}, child: Icon(Icons.add)),
),
);
}
}
class Top extends StatelessWidget {
int num;
Top(this.num);
@override
Widget build(BuildContext context) {
print("Top build...");
return Center(
child: Container(
child: Text("$num", style: TextStyle(fontSize: 50)),
),
);
}
}
- BuildContext는 그림을 그리는 설계도입니다.
- 설계도를 분리해야 개발자가 원하는 부분만 다시 그리기(rebuild)가 가능합니다.
- Top과 Bottom 위젯을 가진 Middle Widget을 설계해서 상태 변화 시 Top과 Bottom만 새로 그리게 됩니다.
Share article