[플러터] 13. StatefulWidget과 MiddleWidget

KangHo Lee's avatar
Dec 27, 2024
[플러터] 13. StatefulWidget과 MiddleWidget

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), ), ), ), ), ], ), ); } }
notion image
  • 플러스 버튼을 누르면 위의 숫자가 올라가는 코드입니다.
  • 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

devleekangho