[flutter] Stateless Widget, Stateful Widget(feat. 위젯의 생명주기)

공부할거야·2022년 10월 1일
0

flutter

목록 보기
3/5

*상태 연결: 앱 상태가 변하는지 변하지 않는지를 의미하며 상태 연결이 되지 않았다는 것은 상태가 없다는 것과 동일하다.

StatelessWidget

상태가 없는 위젯(상태 변화가 없는 정적인 위젯)으로 화면이 로드될 때 한 번만 그려진다. -> 변경이 필요한 Data가 없고 상호 작용에 의해 동작하지 않는다.

StatefulWidget

상태가 연결된 동적인 위젯으로 화면의 상태가 변하면 다시 그려진다. -> 데이터가 변경되는 등의 상호작용으로 인해 위젯이 특정 상태가 될 때 알맞은 처리를 수행하며 동작한다.
스위치 또는 체크 박스 등으로 화면을 변경하는 등 동적으로 화면 변화가 필요한 경우 사용한다.
StatefulWidget은 혼자 화면에 출력할 수 없으며 State라는 클래스가 필요하다. State는 객체로 위젯에 대한 변경 가능한 상태가 유지되는 곳이다.

StatefulWidget과 State가 별도의 클래스인 이유는?
-> 결론적으로 말하자면 성능 때문이다.
tldr 버전은 state 객체가 오래 살아있지만 StatefulWidget은 구성이 바뀔 때마다 버리고 새로 작성된다. mutable widget을 재작성하는 것은 플러터에서 매우 쉬운 일이다.
State는 재구성 될 때마다 날아가지 않기 때문에 복잡한 계산을 피할 수 있고 무언가가 프레임 별로 재구축 될 때마다 state 속성, getter, setter 등을 가져온다.
State는 폐기되지 않으므로 데이터 변경에 대한 응답으로 필요한 경우 Widget을 지속적으로 재구축 할 수 있다.
State 클래스를 상속받는 클래스를 만들고 그 안에 만들어 놓은 위젯을 담는다.


class Practice extends StatefulWidget {
  // StatefulWidget 클래스를 상속받는 Practice에 createState() 함수를 재정의
  // _PracticeSwitch 호출 -> 이를 통해 Practice 클래스가 현재 화면을 주시
  // 주시 중 상태가 변경되면 이를 감지하고 _PracticeSwitch클래스가 화면 갱신
  @override
  State<StatefulWidget> createState() {
    return _PracticeSwitch();
  }
}

class _PracticeSwitch extends State<Practice>{
  var switchValue = false;
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Practice',
        theme: ThemeData(
          primarySwatch: Colors.blue,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        darkTheme: ThemeData.light(),
        home:Scaffold(
            body: Switch(
            value: switchValue,
            onChanged: (value){
              // setState()에 변경된 상태 값을 넣어주면 플랫폼에 전달하여 build가 호출된다. 
              // 이를 통해 다시 Build하는 과정이 일어나며 동적 화면을 구성한다.
              setState((){
              switchValue = value;
            });}
          ),
        )
    );
  }
}

위젯의 상태주기

StatelessWidget: 한 번 Build 후 갱신이 없기 때문에 생명 주기가 없다. 화면이 넘어갈 경우 모든 로직이 종료된다.

StatefulWidget: 10단계의 생명주기가 있다.

  1. 위젯의 상태를 생성하는 createState()
    플러터가 StatefulWidget을 빌드하라는 지시를 받으면 즉시 createState()를 호출해 상태를 생성한다. 이 함수를 통해 다른 생명주기 함수들이 포함된 State 객체를 생성해 위젯의 상태를 생성한다.
class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}
  1. mounted
    모든 위젯에는 bool this.mounted 속성이 있는데 실행하고 있는 페이지가 띄워져 있는지 확인하는 전역 변수이다. createState()를 통해 상태를 생성하면 해당 상태에 buildContext가 할당된다.(buildContext는 위젯이 배치되는 위젯 트리의 위치이다.) buildContext가 할당되면 mounted는 true가 된다. (위젯이 unmounted일 때 setState를 호출하면 오류가 뜬다.)

  2. initState()
    State 객체 생성 후 State 객체의 생성자가 호출되어 State를 초기화 시키는 함수이다. StatefulWidget이 실행할 때 단 한 번만 작동한다. 이 함수를 다시 작동시키기 위해서는 StatefulWidget을 종료 후 다시 시켜야 한다. 보통 controller를 설정하거나 listener를 설정한다.

 @override
 void initState() {
   scrollController.addListener(() {
     if (scrollController.offset >= 600) {
       if (!_isVisibility) {
         _isVisibility = true;
       }
     } else if (scrollController.offset < 600) {
       if (_isVisibility) {
         _isVisibility = false;
       }
     }
   });
   super.initState();
 }
// 출처: https://pcseob.tistory.com/18?category=1022137
  1. didChangeDependencies()
    위젯이 최초 생성될 때 initState 함수 호출 후 바로 didChangeDependencies가 호출된다. 또한 위젯이 의존하고 있는 데이터가 호출될 때 같이 호출된다.
    ex) 업데이트 되는 위젯을 상속한 경우 - 네트워크 호출, API 호출

  2. build()
    이 함수를 통해 위젯이 그려진다. State 클래스에서 반드시 오버라이딩 되어야 하며 Widget을 리턴해야 한다. 최초로 호출되며 변경이 있을 때 또한 setState를 통해 호출된다.

  3. didUpdateWidget(Widget oldWidget)
    부모 위젯이 변경되어 이 위젯이 갱신될 때 호출된다. flutter는 State를 재사용하기 때문에 initState()에서처럼 일부 데이터를 다시 초기화 해야 한다.

  • 이 함수 호출 후 build()를 호출한다. 따라서 didUpateWidget() 내에서 setState() 호출시 build 중복 호출이 된다.
  1. setState()
    데이터(상태)가 변경되었을 때 호출한다. setState 호출 후 build가 다시 실행된다. 화면의 변화가 생겼을 때 사용한다. build가 전부 새로 변화하기 때문에 모든 위젯이 바뀌게 된다.(Futurebuild 같은 데이터를 불러오는 것도 다시 다 불러온다.따라서 setState은 최대한 지양, statelessWidget을 사용)
    setState()는 비동기적이지 않은 callback을 사용 -> callback으로 비동기 사용 불가능

  2. deactivate()
    tree에서 State가 제거될 때 호출된다.

  3. dispose()
    화면이 종료될 때 호출되어 State 객체가 영구히 제거된다. 보통 controller를 종료할 때 사용

  4. mounted is false
    이 상태에서는 state 객체가 다시 mount되지 않으며, setState() 호출시 에러가 발생한다.

참고: https://flutterbyexample.com/lesson/stateful-widget-lifecycle#4-didChangeDependencies
https://devmg.tistory.com/186

profile
아마도?

0개의 댓글