Stateful Widget은 변경 가능한 위젯이다.
- state는 위젯이 빌드될 때 동기적으로 읽을 수 있고 위젯의 lifecycle동안 변경 가능한 정보이다.
기본 코드 구성
@immutable
class App extends StatefulWidget {
const App({super.key});
@override
State<App> createState() => _AppState();
}
class _AppState extends State<App> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: const Color(0xFFF4EDDB),
body: Container(),
),
);
}
}
Stateful로 바꾸고
이런 에러가 발생했다.
이 글을 보고 해결했음.
- main()이나 initState() 메서드 내에서 변경을 했을 때 핫 리로드가 실패하는 현상으로 VM을 재부팅하여 다시 앱을 실행하면 해결됨.
int counter = 0;
void onCliked() {
// 단순히 아래처럼 counter의 값을 변경하는 것은
// 플러터에서 알아차리지 못함.
// counter = counter + 1;
// react처럼 setState 함수를 이용해서 알려줘야 함.
// 무조건 counter ++; 이 setState 내에 있어야 하는 것은 아니고
// setState함수가 실행되면서 build메서드를 실행시킴.
setState(() {
counter++;
});
}
List<int> numbers = [];
void onCliked() {
setState(() {
numbers.add(numbers.length);
});
}
//build
for (var n in numbers) Text('$n'),
flutter에서는 생각보다 state가 많이 사용되지 않음.
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
textTheme: const TextTheme(
titleLarge: TextStyle(
color: Colors.red,
),
),
),
// 자식 MyLargeTitle
//MyLargeTitle은 MaterialApp의 자식이고
//부모의 ThemeData를 사용하기 위해서 context를 사용.
Widget build(BuildContext context) {
return Text(
'My Large title',
style: TextStyle(
fontSize: 30,
// context로 부모 요소에 접근하여 데이터를 가져오는 방법.
color: Theme.of(context).textTheme.titleLarge?.color,
),
);
class _MyLargeTitleState extends State<MyLargeTitle> {
//initState를 사용하지 않고 아래처럼 해도 됨.
//근데도 initState를 사용하는 상황
// 부모 요소에 의존하는 데이터를 초기화해야 하는 경우
// API에서 데이터를 받아와 이니셜라이즈.
// 그 때 build 메서드보다 initState가 항상 먼저 호출 됨.
int count = 0;
//상태를 초기화하기 위한 메서드(옵션)
@override
void initState() {
super.initState();
print('initState!');
}
@override
Widget build(BuildContext context) {
print('build!');
return Text(
'My Large title',
style: TextStyle(
fontSize: 30,
// context로 부모 요소에 접근하여 데이터를 가져오는 방법.
color: Theme.of(context).textTheme.titleLarge?.color,
),
);
}
}
위젯이 제거되기 전에 실행하고 싶은 코드를 기입.
// 토글 만들어주고.
class _AppState extends State<App> {
bool showTitle = true;
void toggleTitle() {
setState(() {
showTitle = !showTitle;
});
//
showTitle ? const MyLargeTitle() : const Text('nothing'),
IconButton(
onPressed: toggleTitle,
icon: const Icon(Icons.remove_red_eye))
}
토글 눌러서 MyLargeTitle()이 제거될 때 디버그 콘솔에 dispose가 출력.
요약
stateful widget은 lifecycle을 가지고 있다.
가장 중요한 메서드는 initState와 dispose, build이다.
- build: UI 생성
- initState : build 이전에 호출되는 메서드
- dispose : 위젯이 위젯트리에서 제거될 때 호출