Tech & Programming/모바일(Android, Flutter)

플러터 StatelessWidget? StatefulWdiget?

소스코드 요리사 2021. 8. 21. 00:45

최근 프로젝트 막바지(?) 에 이르러 정신없이 일 만하고 있습니다.

회사를 이직한 후 약 2년간의 경험을 리뷰했던 글의 말미에 적었듯이, 최근 안드로이드, iOS 어플리케이션을 플러터 전환을 하는 프로젝트를 진행하고 있습니다. 이 프로젝트가 잘 풀리지 않아서 요즘 엄청 바쁘게 일하고 있습니다.

그래서, 블로그에 꾸준히 글을 적어야지 하고 글 주제는 많이 수집 해놨는데 글 쓰는 시간이 잘 안나네요.

게다가 예전에 쓰려고 뽑아 놓은 주제들은 시간이 갈 수록 구(old) 기술이 되어 버렸거나 너무 늦었다 라는 감을 지울 수 없는 주제가 많네요.

서두가 길었습니다.

시간이 없는 관계로 최근 플러터 프로젝트를 들어가면서 개인적으로 정리해 놓은 내용 중에 제일 깔끔하고 수정이 필요 없어 보이는 녀석으로... 하나 공유 하고자 합니다.

플러터를 시작하시면 가장 먼저 접하고, 가장 개념을 빨리 잡아야하는 위젯에 대한 내용입니다.

바로 StatelessWidget 과 StatefulWidget 에 대한 내용입니다.

StatelessWidget?

  • 상태가 없는 위젯
  • StatefulWidget 은 CreateState() 메소드를 가지고, State는 Widget build(BuildContext context) 을 가진다.
  • 사용자와 상호 작용이 없는 위젯, 터치와 같은…(TextView)
  • 특별한 생명주기가 없음
    • 앱 최초 실행 시 : Widget 의 생성자 호출 -> createElement() -> build() 호출 됨
    • 핫리로드 시 : Widget 의 생성자 호출 -> build() 호출 됨

StatefulWidget?

  • 상태가 있는 위젯
  • StatelessWidget 상속 받는 위젯이 Widget build(BuildContext context) 메소드를 가진다.
  • 사용자와 상호 작용을 하는 위젯, 터치와 같은…. (CheckBox, EditBox)
  • 생명주기가 존재함

  • createState()
    • statefullWidget 에서 State 생성의 역할을 진행
  • initState()
    • State가 트리에 삽입될 때 호출 되며, State가 생성될 때 1번만 호출됨.
    • initState() 에서 State 객체를 위젯이 구독함
    • 역할
      • 생성된 위젯 인스턴스의 BuildContext에 의존적인 것들의 데이터 초기화
      • 동일 위젯트리내에 부모위젯에 의존하는 속성 초기화
      • Stream 구독, 알림변경, 또는 위젯의 데이터를 변경할 수 있는 다른 객체 핸들링.
    •  didCahngeDepndencies()
      • State 개체의 종송성이 변경될 때 호출된다.
      • initSate() 호출 직후 호출되고, 이 State의 위젯이 의존하는 위젯이 변경되면 호출된다.
      • 나중에 변경된 InheritedWidget 을 참조하는 경우 프레임워크 이 메소드를 호출하여 변경사항을 알림. (즉, 위젯 A가 위젯 B를 상속 받았는데, 위젯 B가 업데이트 될 때 호출된다.
      • 이 메소드를 사용하는 서브클래스는 이어 build가 호출되기 때문에 거의 재정의 할 필요가 없다. 하지만, 네트워크 호출을 수행하고, 이 작업 후 모든 빌드에 대해 수행을 해야하는 경우 이 메서드를 재정의
  • build()
    • 이 상태를 사용하는 위젯을 생성(Render) 함.
    • 아래 상태일 때 호출되며 자주 호출 됨.
      • initState 호출 한 후.
      • didUpdateWidget호출 한 후.
      • setState 대한 호출을받은 후.
      • 이 State 개체의 종속성이 변경된 후 (예 : 이전 build 변경에서 참조 된 InheritedWidget ).
      • deactivate호출 한 후 다른 위치의 트리에State개체를 다시 삽입합니다.
  • setState()
    • State가 변경되었음을 프레임워크에 알리는 함수
  • didUpdateWidget()
    • 위젯 구성이 변경될 때마다 호출
    • 위 위젯이 새위젯을 표시하도록 트리의 위치를 업데이트 했을 때, 새 위젯을 참조하도록 State개체의 위젯 속성을 업데이트 한 다음 해당 메소드 호출 즉, 부모 위젯이 재빌드 되어 갱신되었을 때 호출됨.
    • 이 메소드 호출 뒤에 build가 항상 호출됨. 따라서, 이 함수 안에 setState를 위치하면 안됨.
  • deactivate()
    • Tree에서 State가 제거 될 때 호출.
    • 어떤 경우에는 프레임워크가 제거된 State 객체가 트리의 다른 부분에 넣기도 함.
      이 때에는 Build가 함께 호출됨. 재정의 하는 경우 super 를 호출하여 메서드를 종료해야함.
    • dispose() 호출전에 호출됨.
  • dispose()
    • State 객체가 Tree 에서 영구히 제거될 때 호출.
    • 재정의 하는 경우 super 를 호출하여 메서드를 종료해야함.이 State객체에 대한 구독을 종료
  • ressemble()
    • hot reload 실행 시 호출되고 이어서 build() 호출됨

실제 예제를 통한 로그 분석

  • 새로 시작 시
    • Widget : 생성자 -> createElement() -> createState()
    • State: 생성자 -> initState() -> didChangeDependencies() -> build() -> ressemble()
  • 핫리로드 시
    • Widget : 생성자
    • State: didUpdateWidget() -> Build()
  • setState() 클릭 시: Build() 호출이 일어남.

  • 안드로이드 onPause, onStop, onStart, onResume 같은 것이 없다.
  • 새로운 Route 가 나와도 호출되는 주기 관련 메소드가 없다.
  • State의 생성자 쪽에 로직이 수정되면 핫리로드로는 반영이 안됨. State 객체를 재생성 안함.
  • 보통 statefulWidget 에서 setState 를 통해 statelessWidegt 을 rebuild 시켜서 위젯 내용을 갱신시키거나 상태관리 플러그인 및 방법론에 의해서 stateless 위젯이 갱신되면서 앱의 내용이 변경된다.

[레퍼런스]

* https://jaceshim.github.io/2019/01/28/flutter-study-stateful-widget-lifecycle/

* https://velog.io/@ieed0205/Flutter-1.-Lifecycle%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0

* https://brunch.co.kr/@mystoryg/139

* https://chajinjoo.netlify.app/Flutter/2002/200227_statefulWidgetLifeCycle/