
setState애 대해 이야기하기 전, StatefulWidget 먼저 알고 가자!
📍 StatefulWidget
StatefulWidget은 변경될 수 있는 상태를 가지고 있는 위젯이다.
여기서 상태란? 위젯이 빌드되는 동시에 읽을 수 있으며, 위젯의 생명 주기동안 변경할 수 있는 정보를 의미한다. StatefulWidget은 UI의 일부분이 동적으로 변화할 때 유용하게 사용된다.
아래는 StatefulWidget을 사용할 때의 기본 코드 구조 예시!
class Example extends StatefulWidget {
Example({Key? key}) : super(key: key);
_ExampleState createState() => _ExampleState(); // State 생성
}
class _ExampleState extends State<Example> {
Widget build(BuildContext context) {
return ... // UI에서 변화할 부분
}
}
StatefulWidget 인스턴스는 mutable(값이 변함)하지 않음.
StatefulWidget 인스턴스 자체는 immutable(불변) 하지만 mutable한 상태(state)를 별도로 관리함.
상태(state)가 저장되는 곳은 State 오브젝트이며, State 오브젝트는 createState() 메소드를 통해 생성됨.
따라서 UI에서 변화할 부분은 State 클래스의 build 메소드 리턴 값에 들어가는 것!
📍 SetState
특정한 위젯 내에서 단기적으로 쓰이고 말 때 사용하면 편한 상태 관리 방법
- setState( )는 StatefulWidget에서 특정 오브젝트의 상태(값)를 변경하기 위해 사용하는 메소드이다.
- setState( ) 안에서 상태를 변경하면 setState( )가 Flutter 프레임워크에 변경됨을 알리고, 변경된 상태를 기반으로 build( ) 메소드를 실행시킨다.
즉, setState( ) 함수 안에서의 호출은 State에서 무언가 변경된 사항이 있음을 Flutter Framework 에 알려주는 역할이고, 이로 인해 UI 에 변경된 값이 반영되도록 build 메소드가 다시 실행된다는 것!
아래는 SetState 사용 예시!
0에서 시작해서 1씩 늘어나는 Counter를 만들어 보자.
class Counter extends StatefulWidget {
Counter({Key? key}) : super(key: key);
_CounterState createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _counter = 0;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('StatefulWidget Example'),
),
body: Center(
child: Text(
'현재 숫자: $_counter',
),
),
);
}
}
하지만 위의 코드에는 변경되는 UI가 없음...
숫자는 계속 0이기 때문에 아래와 같은 화면만 계속 보여줌.
class Counter extends StatefulWidget {
Counter({Key? key}) : super(key: key);
_CounterState createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _counter = 0;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('StatefulWidget Example'),
),
body: Center(
child: ElevatedButton(
child: Text(
'현재 숫자: $_counter',
),
onPressed: () {
_counter++; // 버튼 클릭 시, 숫자 1 증가.
},
),
),
);
}
}
Counter에 숫자를 증가시키는 버튼을 추가해 본다...
버튼 클릭하면 화면의 숫자가 증가할 줄 알았는데, 버튼을 눌러도 화면의 숫자는 0이다...
이때 setState()을 사용하여 상태를 변경할 수 있다.
class Counter extends StatefulWidget {
Counter({Key? key}) : super(key: key);
_CounterState createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _counter = 0;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('StatefulWidget Example'),
),
body: Center(
child: ElevatedButton(
child: Text(
'현재 숫자: $_counter',
),
onPressed: () {
setState(() { // setState() 추가.
_counter++;
});
},
),
),
);
}
}
버튼을 클릭하면 숫자가 증가함!
setState( )가 변경을 Flutter 프레임워크에 알려서 증가한 숫자(변경된 상태)를 기반으로 build() 메소드를 실행하는 것! 그래서 이제 버튼을 누르면 화면에도 숫자가 증가하는 게 보여지는 것!
① 전역 상태 관리
특정 위젯 내에서만 사용하는 상태 관리에 적합함.
그렇다 보니 뷰 전체, 앱 전체에 영향을 미치는 상태 관리에 한계가 있음.
② 복잡한 상태 관리
페이지 내 여러 상태가 상호 작용하는 복잡한 UI 구성 시, 코드 구성도 복잡해질 수 있음.
③ 최적화 문제
setState 메소드는 관련된 위젯트리 전체를 재구성함.
그렇다 보니 크고 복잡한 위젯트리에서 불필요한 랜더링이 발생할 수 있음.
이런 이유로 상태관리 라이브러리 Provider와 RiverPod을 사용하는 것!
다음 시간에 상태관리 라이브러리 Provider와 RiverPod에 대해 차근차근 알아보자!