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