Stateful widget

Stupefyee's avatar
Dec 27, 2024
Stateful widget

1. Stateful Widget 정의

  • 상태를 가질 수 있는 위젯
  • 상태 변화에 따라 UI를 업데이트할 수 있음

2. 구성

1. StatefulWidget 클래스

  • createState() 메서드로 State 객체 생성

2. State 클래스

  • 상태 관리 및 UI 업데이트 담당
  • setState() 호출 시 화면 재구성

3. 코드 분석

1. HomePage: StatefulWidget 정의

  • 상태를 가지며, 상태 변화에 따라 UI 갱신

2. _HomePageState: State 클래스

  • num 변수로 상태 관리
  • setState() 호출로 UI 업데이트
  • UI 업데이트 과정
      1. 버튼 클릭 → num++ 실행
      1. setState() 호출 → build() 재실행
      1. 화면에 num 값 갱신

3. 예시 코드

void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { print("MyApp build....1"); return MaterialApp( home: HomePage(), ); } } class HomePage extends StatefulWidget { @override State<HomePage> createState() => _HomePageState(); // HomePage의 상태를 관리할 State 객체(_HomePageState) 생성 } class _HomePageState extends State<HomePage> { int num = 1; // 상태 변수 num, 초기 값은 1 @override Widget build(BuildContext context) { print("HomePage build....2"); // HomePage가 빌드될 때마다 출력 return Scaffold( body: Column( children: [ Expanded( child: Center( child: Container( child: Text("$num"), // 화면에 num 값 출력 ), ), ), Expanded( child: Center( child: Container( child: ElevatedButton( onPressed: () { num++; // 버튼 클릭 시 num 값을 1 증가 setState(() {}); // 상태 변화 알리고 UI를 갱신하도록 Flutter에 요청 print("num: $num"); // 상태 변화 후 num 값 출력 }, child: Icon(Icons.add), // 버튼에 더하기 아이콘 추가 ), ), ), ), ], ), ); } }
notion image
💡
현재 HomePage가 Stateful 이여서 setState를 하게 되면 Homepage의 모든 자식들이 다시 그려지는 문제가 존재
>> 하나의 BuildContext내에서 모든 그림을 관리하고 있어 생기는 문제
notion image

4. 단점을 보완한 예시 코드

import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: HomePage(), ); } } class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { print("HomePage build..."); // HomePage가 빌드될 때 출력 return Scaffold( body: Middle(), // Middle 위젯을 화면에 표시 ); } } class Middle extends StatefulWidget { const Middle({ super.key, }); @override State<Middle> createState() => _MiddleState(); // Middle 상태 객체 생성 } class _MiddleState extends State<Middle> { // 상태 변수 num, 초기 값은 1 int num = 1; // 상태 변경 메서드 increase() increase() { num++; // num 값 증가 setState(() {}); // 상태가 변경되었음을 알리고 UI 갱신 } @override Widget build(BuildContext context) { print("Middle build..."); // Middle이 빌드될 때 출력 return Column( children: [ Expanded( child: Top(num), // 상태(num)를 Top 위젯에 전달 ), Expanded( child: Bottom(increase), // 행위(increase 메서드)를 Bottom 위젯에 전달 ), ], ); } } class Bottom extends StatelessWidget { final Function increase; // increase 메서드를 받아올 변수 Bottom(this.increase); // 생성자에서 increase 메서드 받기 @override Widget build(BuildContext context) { print("Bottom build..."); // Bottom이 빌드될 때 출력 return Center( child: Container( child: ElevatedButton( onPressed: () { increase(); // 버튼 클릭 시 increase() 호출 }, child: Icon(Icons.add), // 버튼에 더하기 아이콘 추가 ), ), ); } } class Top extends StatelessWidget { final int num; // num 값을 받아올 변수 Top(this.num); // 생성자에서 num 값을 받기 @override Widget build(BuildContext context) { print("Top build..."); // Top이 빌드될 때 출력 return Center( child: Container( child: Text( "$num", style: TextStyle(fontSize: 50), // num 값을 화면에 표시 ), ), ); } }
💡
Middle()을 생성해 BuildContext를 분리하여 따로 관리
>> 필요한 곳만 다시 Build함
notion image
 
Share article

stupefyee