본문 바로가기
앱 개발 공부

플러터 기본 학습 - 상태 관리 (1) state, Stateful widget

by polissage 2024. 1. 12.
728x90

플러터에서는 상태가 변경되면 UI를 명령어로 직접 변경하지 않는다(예: widget.setText). 상태를 변경하면 이에 맞게 UI를 리빌드한다.(declarative)

State

상태는 UI를 변경하도록 영향을 미치는 데이터를 가리키며, 일시적인 상태(Ephemeral)와 app 수준의 상태 2가지가 있다.

일시적 상태는 위젯 1개에서 StatefulWidget 내 setState 메소드로 간단하게 표현할 수 있다.

일시적 상태

  • PageView의 현재 페이지
  • 복잡한 애니메이션의 현재 진행 상태
  • BottomNavigationBar에서 현재 선택된 탭

app state

앱 상태는 여러 곳에서 공유되거나 여러 세션에서 유지하려고 하는 상태를 가리킨다.

  • 사용자 환경 설정
  • 로그인 정보
  • 소셜 네트워킹 앱의 알림
  • 이커머스 앱의 쇼핑 카트
  • 뉴스 앱에서 기사의 읽음/읽지 않음 상태

앱 상태와 일시적 상태의 구분

단일 위젯에 국한되는 일시적 상태는 State나 setState()로 구현할 수 있으며, 그 외의 상태는 앱 상태로 간주할 수 있다.

Stateful widget

 

StatefulWidget class - widgets library - Dart API

A widget that has mutable state. State is information that (1) can be read synchronously when the widget is built and (2) might change during the lifetime of the widget. It is the responsibility of the widget implementer to ensure that the State is promptl

api.flutter.dev

1. Stateless widget과의 공통점과 차이점

  1) 공통점: build method 호출하여 UI 렌더링

  2) 차이점

    ① Stateless widget: 데이터가 변하지 않는 위젯

    ➁ Stateful widget은 상태를 가지며, 동적으로 변경되는 인터페이스를 표현 가능하다. 위젯 내부에 state라는 또 다른 클래스를 가지며, 2개의 클래스가 결합되어 Stateful widget을 구성한다.

 

2. Stateful widget의 특징

  1) build 메소드는 state class가 가지고 있고 state class가 랜더링을 한다.

  2) Stateful widget이 리빌드되는 경우

   ① child 위젯의 생성자를 통해 새로운 데이터가 전달될 때(stateless widget과 동일)

   ➁ internal state가 바뀔때

 

3. 구성: Stateful widget은 2개의 클래스로 구성된다.

Stateful widget은 Widget 클래스를 상속하는데 이는 원래 immutable한 클래스이다. Stateful widget은 state의 변화를 반영해야 하므로, mutable한 클래스를 만들어서 2개를 서로 연결해준다.

 

class MyStatefulWidget extends StatefulWidget { }

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return Container(
    );
  }
}
//State의 generic type을 MyStatefulWidget class로 지정하여 MyStatefulWidget과 _MyStatefulWidgetState를 연결해준다.

 

_MyStatefulWidgetState가 State를 상속받는데 State의 generic type이 MyStatefulWidget이므로 _MyStatefulWidgetState 클래스는 오직 MyStatefulWidget 타입만을 갖게 된다.

 

createState 메소드로 연결하는 다른 방법.

class MyStatefulWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyStatefulWidgetState();
  }
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return Container(
    );
  }
}

 

createState 메소드는 반드시 State 타입의 객체를 리턴해야 하고, 그 객체는 StatefulWidget 타입이며 그 객체는 _MyStatefulWidgetState class에 근거하여 만들어진다.

 

createState 메소드는 Stateful widget이 생성될 때마다 호출된다. Stateless widget은 빌드 메소드에서 생성한 객체를 반환하지만, Stateful widget은 createState 메소드에서 생성된 객체(위젯의 가변 상태를 State 객체에 저장)를 반환한다.

예제- 버튼 클릭시 숫자 올라가는 카운터

state를 변화시키려면 빌드 메소드를 호출하여 위젯을 리빌드해야 한다. stateless widget 내에서 setState 메소드로 빌드 메소드를 호출할 수 있다.

class MainApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return MainAppSate();
  }
}

class MainAppSate extends State<MainApp> {
  int counter = 0;
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text('버튼 클릭 수: $counter'), 
              //결과를 보여주는 Text 위젯은 stateless 위젯이어서, 상태를 변경하려면 빌드 메소드를 호출해주어야 한다.
              ElevatedButton(
                  onPressed: () {
                    setState(() {
                      counter++;
                      //클릭시 값이 1씩 증가
                    });
                    //setState 메소드로 빌드 메소드를 호출해준다.
                  },
                  child: Text('Press',))
            ],
          ),
        ),
      ),
    );
  }
}

 

클릭하면 카운터가 올라간다.

728x90

댓글