Skip to content

Flutter Life Cycle

seoreal edited this page Sep 24, 2019 · 2 revisions

StatelessWidget / StatefulWidget

  • Flutter의 모든 UI 요소들은 Widget 이다.
  • StatelessWidget : Immutable State / StatefulWidget : Mutable State
스크린샷 2019-09-24 오후 2 22 34

Stateful에선 state object를 통해 build를 하게 된다.


LifeCycle

1. 전체적인 과정

스크린샷 2019-09-24 오후 2 40 12 스크린샷 2019-09-24 오후 2 41 40
  1. Stateful의 Constuctor가 제일 먼저 호출이 됩니다.
  2. 그다음 createState() : State를 생성
  3. initState() : State 초기화
  4. build() : Redering
  5. Stateful build()가 실행될때 Stateless 의 Constructor가 실행이 됩니다.
  6. 이어서 Stateless의 build()가 실행되어 화면에 무언가를 출력하게 됩니다.
  7. 이 후 사용자의 입력 및 이벤트가 발생하면, Stateful의 setState()가 호출로 State의 변화가 발생합니다.
  8. 그다음 4.5,6의 과정이 재 실행됩니다.
  9. 이때 Widget의 변경이 발생(소스변경같은 상황), 그래서 Stateful 의 didUpdateWidget()이 호출되고
  10. Statefule의 build()가 실행되고 다시 4,5,6번이 실행이 됩니다.

2. StateFul Widget LifeCyce

> 다음과 같은 단계를 포함하고 있다.
* createState()
* mounted == true
* initState()
* didChangeDependencies()
* build()
* didUpdateWidget()
* setState()
* deactivate()
* dispose()
* mounted == false

1. createState()

StatefulWidget을 빌드하도록 지시하면 즉시 [createState()]가 호출된다. 이 메서드는 반드시 존재해야 한다.

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

2. mounted is true

createState가 state클래스를 생성하면 buildContext는 state에 할당된다. (BuildContext 는 위젯이 배치된 위젯 트리의 위치를 단순화 한 것이다.) 모든 위젯은 bool형식의 this.mounted 속성을 가지고 있다. buildContext가 할당되면 true를 리턴한다. 위젯이 unmounted 상태 일 경우, setState를 호출하면 error가 발생한다.

  • tip: 이 속성은 state에 setState()를 호출할때 유용하지만 해당 메서드가 언제, 얼마나 자주 호출 되는지는 명확하지 않다. 아마도 stream이 업데이트에 대한 응답으로 호출되는것 같다. setState()호출전에 State가 존재함을 if (mounted) {...로 확인 할 수 있다.

3. initState()

위젯이 생성될때 생성자 진행 후, 처음으로 호출되는 메서드로 오직 한번만 호출된다. 또한 반드시 super.initState()를 호출해야 한다.

이 함수의 @override method를 사용할 때, best time은

  • 생성된 위젯 인스턴스의 BuildContext에 의존적인 것들의 데이터 초기화
  • 동일 위젯트리내에 부모위젯에 의존하는 속성 초기화
  • Stream 구독, 알림변경, 또는 위젯의 데이터를 변경할 수 있는 다른 객체 핸들링.
@override
initState() {
  // 부모의 initState호출
  super.initState();
  // 이 클래스에 리스너 추가
  cartItemStream.listen((data) {
    _updateWidget(data);
  });
}

4. didChangeDependencies()

이 메서드는 위젯이 최초 생성될때 initState 다음에 바로 호출 된다. 또한 위젯이 데이터에 의존하는 객체가 호출될 때마다 호출된다. 예를 들면 업데이트되는 InheritedWidget 에 의존하는 경우. build 는 항상 didChangeDependencies 호출 후에 실행되는 점을 명심해야 한다. 잘 사용하지 않지만 BuildContext.inheritFromWidgetOfExactType 을 호출하기 위해서 첫단계 시작점이다. 이건 데이터를 상속받는 위젯의 변경사항을 Listening 하게 만든다. 공식문서 또한 상속한 위젯이 업데이트 될때 네트워크 호출(또는 다른 비용이 큰 액션)(역자주: API호출)이 필요한 경우 유용하다고 함.

5. build()

필수이며 재정의 대상(@override)이고 반드시 Widget을 리턴해야 한다. 이 메서드는 자주 호출된다(fps + render로 생각하세요). 플러터의 모든 gui는 Padding, Center 조차도 child 또는 children을 가진 위젯 이라는것을 기억하라.

6. didUpdateWidget(Widget oldWidget)

didUpdateWidget()는 부모 위젯이 변경되어 이 위젯을 재 구성해야 하는 경우, 함수가 호출되고(다른 데이터를 제공해야하기 때문에) 같은 runtimeType과 함께 다시 만들어진다. 이것은 플러터가 state를 재 사용하기 때문이다. 이 경우 initState()에서 처럼 일부 데이터를 다시 초기화 해야 한다.

build() 메서드가 Stream 또는 other object와 같이 변경 가능한 데이터에 의존적인 경우 old object에서 구독을 취소하고 didUpdateWidget()에서 새로운 인스턴스에 다시 구독 해야한다.

tip: 이 메서드는 기본적으로 위젯의 State와 관련된 위젯을 rebuild 해야 하는 경우, initState()을 대체한다.

@override
void didUpdateWidget(Widget oldWidget) {
  if (oldWidget.importantProperty != widget.importantProperty) {
    _init();
  }
}

7. setState()

setState() 메서드는 플러터 프레임워크 자체적, 또는 개발자로 부터 자주 호출된다. '데이터가 변경되었음’을 프레임워크에 알리는데 사용되며 build context의 위젯을 다시 build하게 한다. setState()는 비동기화 할 수 없는 callback을 받는다.(역자주: callback으로 비동기를 사용할 수 없다는 말임).

필요에 따라 자주 호출 할 수 있는 이유는 다시 그리는데(repainting) 소용되는 비용이 저렴하기 때문이다.

void updateProfile(String name) {
 setState(() => this.name = name);
}

8. deactivate()

이 메서드는 거의 사용 되지 않는다.

deactivate()tree에서 State를 제거할 때 호출 되지만, 현재 프레임 변경이 완료되기 전에 다시 삽입 될 수 있다.이 메서드는 State객체가 tree의 한 지점에서 다른 지점으로 이동 할 수 있기 때문에 기본적으로 존재한다.

9. dispose()

영구적인 State Object가 삭제될때 호출된다. 이 함수는 주로 Stream 이나 애니메이션 해제 시, 사용된다.

10. mounted is false

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