StatelessWidget만 만들다가 StatefulWidget에 대해 배웠다.
StatefulWidget을 쓰면 setState(){} 를 사용할수 있다. 해당 Widget을 새로 빌드한다.
아래의 예제는 StatefulWidget 에 int num =1 을 넣어 상태를 저장하고 이것을 변경할때마다 Widget을 다시 빌드함으로써 변경된 상태를 나타낼수 있다.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    );
  }
}
class HomePage extends StatefulWidget {
  @override
  State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
  int num = 1;
  @override
  Widget build(BuildContext context) {
    print("나그려짐");
    return Container(
      color: Colors.yellow,
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          children: [
            Expanded(
              child: Container(
                color: Colors.red,
                child: Align(
                  child: Text(
                    "${num}",
                    style: TextStyle(
                        color: Colors.white,
                        fontWeight: FontWeight.bold,
                        fontSize: 100,
                        decoration: TextDecoration.none),
                  ),
                ),
              ),
            ),
            Expanded(
              child: Container(
                color: Colors.blue,
                child: Align(
                  child: ElevatedButton(
                    style:
                    ElevatedButton.styleFrom(backgroundColor: Colors.red),
                    onPressed: () {
                      num++;
                      setState(() {});
                    },
                    child: Text(
                      "증가",
                      style: TextStyle(
                        color: Colors.white,
                        fontWeight: FontWeight.bold,
                        fontSize: 100,
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}여기서 문제점은 setState를 호출할떄마다 전체의 화면이 다 다시 그려진다.
컨텍스트 분리하지않으면 전체가 다시 그려짐
context를 분리하자.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    );
  }
}
class HomePage extends StatefulWidget {
  @override
  State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
  // 1. 상태
  int num = 1;
  // 2. 행위
  void add(){
    num++;
    setState(() {});
  }
  @override
  Widget build(BuildContext context) {
    print("나그려짐");
    return Container(
      color: Colors.yellow,
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          children: [
            Header(num: num),
            Bottom(add: add),
          ],
        ),
      ),
    );
  }
}
class Bottom extends StatelessWidget {
  final add;
  Bottom({required this.add});
  @override
  Widget build(BuildContext context) {
    print("Bottom 다시 그려짐");
    return Expanded(
      child: Container(
        color: Colors.blue,
        child: Align(
          child: ElevatedButton(
            style:
            ElevatedButton.styleFrom(backgroundColor: Colors.red),
            onPressed: () {
              add();
            },
            child: Text(
              "증가",
              style: TextStyle(
                color: Colors.white,
                fontWeight: FontWeight.bold,
                fontSize: 100,
              ),
            ),
          ),
        ),
      ),
    );
  }
}
class Header extends StatelessWidget {
  const Header({
    super.key,
    required this.num,
  });
  final int num;
  @override
  Widget build(BuildContext context) {
    print("Header 다시 그려짐");
    return Expanded(
      child: Container(
        color: Colors.red,
        child: Align(
          child: Text(
            "${num}",
            style: TextStyle(
                color: Colors.white,
                fontWeight: FontWeight.bold,
                fontSize: 100,
                decoration: TextDecoration.none),
          ),
        ),
      ),
    );
  }
}컨텍스트를 분리하여 상태가 변경되는 부분만 sf로 만든다.
상태와 행위를 header에 넣으면 bottom은 다시 안그려도된다
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    );
  }
}
class HomePage extends StatelessWidget {
  const HomePage({super.key});
  @override
  Widget build(BuildContext context) {
    print("HomePage 다시 그려짐");
    return Container(
      color: Colors.yellow,
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          children: [
            Header(),
            Bottom(),
          ],
        ),
      ),
    );
  }
}
class Bottom extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("Bottom 다시 그려짐");
    return Expanded(
      child: Container(
        color: Colors.blue,
      ),
    );
  }
}
class Header extends StatefulWidget {
  @override
  State<Header> createState() => _HeaderState();
}
class _HeaderState extends State<Header> {
  int num = 1;
  void add() {
    num++;
    setState(() {});
  }
  @override
  Widget build(BuildContext context) {
    print("Header 다시 그려짐");
    return Expanded(
      child: Container(
        color: Colors.red,
        child: Align(
          child: Column(
            children: [
              Text(
                "${num}",
                style: TextStyle(
                    color: Colors.white,
                    fontWeight: FontWeight.bold,
                    fontSize: 100,
                    decoration: TextDecoration.none),
              ),
              ElevatedButton(
                  onPressed: () {
                    add();
                  },
                  child: Text("증가"))
            ],
          ),
        ),
      ),
    );
  }
}그림을 그리다보면, 상태의 화면과 행위의 화면이 다를때 가장 가까운 공통부모를 sf로 두고 상태와 행위를 전달한다
Share article