Mobile/Flutter

[Flutter] Dive into StatefulWidget. Flutter Widget Library.

개발왕 금골드 2022. 11. 26. 13:56
반응형

Introduce

  • 상태 변경이 가능한 위젯이다.
  • 상태란, 위젯이 완성될 때 동기적으로 읽을 수 있는 정보이며, 위젯의 수명 동안 변경될 수 있는 정보이다.
  • StatefulWidget의 상태 변경은 setState()를 이용해서 변경이 가능하다.
  • StatefulWidget 인스턴스 자제는 Immutable이며, createState 메서드에 의해 생성된 State 객체에 변경 가능한 상태를 저장한다.
class ItemCounter extends StatefulWidget {
  final String name;

	ItemCounter({this.name});

  @override
  _ItemCounterState createState() => _ItemCounterState();
}

class _ItemCounterState extends State<ItemCounter> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
				setState(() {
					count++;
				}
			},
			child: Text('${widget.name}: $count')
    );
  }
}

Change State

  • Framework는 setState()가 호출될 때마다 createState() → build()를 재호출하여 화면을 다시 그린다.
  • setState()가 호출되면 Element가 갖고 있는 State에 dirty가 마킹된다. dirty가 마킹된 State의 children들은 다음 프레임에서 rebuild 된다.
  • State가 변경된 순간 oldWidget은 사라지고 새로운 변경사항이 반영된 Children Widget이 생성되고 oldWidget이 위치하고 있던 Widget Tree에 insert 된다.
  • Widget Tree 안에서 새로운 Widget으로 변경되었지만 Element Tree는 변경되지 않고 변경된 위젯과 연결된다. (상태가 변경되었다는 것은 Widget 자신의 상태가 변경된 것이지, 기본적으로 Stateless Element or Stateful Element 자체가 변경된 것은 아니기 때문에 가능하다.)
  • 다시 말해서 Wdiget Tree의 Widget 생명주기보다 Element Tree의 Element 생명주기가 더 길다는 것을 의미하며, Original Widget이 변경되더라도 Element는 여전히 Tree에 attached() 되어 있다.

StatefulWidget in Widget Tree

  • StatefulWidget은 GlobalKey를 사용한 경우 Widget Tree 내에서 다른 위치로 이동하더라도 동일한 State Object를 유지한다.
  • GlobalKey가 있는 Widget이 이동할 때, Framework는 이전 위치에서 새 위치로 하위 트리를 다시 만드는 대신 해당 위젯과 관련된 고유한 하위 트리를 이식하여 이 속성을 활용한다.
  • StatefulWidget과 연결된 State object는 하위 트리의 나머지 부분과 함께 이식된다. 즉, State object가 새 위치에서 다시 생성되는 대신 재사용된다. (물론, 동일한 애니메이션 프레임의 새 위치에 삽입할 때 가능하다.)

Performance considerations

  • State는 leaves까지 밀어 넣는 것이 좋다. (상태가 변경될 때마다 전체 페이지가 변경되는 것보다 leaf가 변경되는 것이 더 효율적이다.)
  • build()에서 생성하는 위젯에 의해 생성되는 노드 수를 최소화한다.
  • 하위 트리가 변경되지 않으면 해당 하위 트리를 나타내는 위젯을 캐시 하여 재사용하는 것이 좋다.
  • 가능한 경우 const Widget을 사용하는 것이 좋다.
  • 하위 트리의 깊이, 유형을 변경하지 않는 것이 좋다. (가능하면 속성으로 제어한다.)
  • 재사용 가능한 UI를 만들 때 helper Method보다 Widget을 사용하는 것이 좋다.

State<T extends StatefulWidget> class

  • StatefulWidget의 로직 및 내부 상태를 작성하는 위젯 클래스.
  • State는 위젯이 작성될 때 동기적으로 읽을 수 있고 위젯 수명 주기 동안 변경될 수 있는 정보를 담고 있다.
  • 이러한 상태가 변경될 때 State.setState()를 사용하여 통보하는 것이 필요하다.

StatefulWidget Lifecycle

화면 구축

  • createState()
    • Flutter는 StatefulWidget을 작성하라는 명령을 받는 즉시 createState()를 호출한다.
  • mounted is true
    • createState()로 State 클래스를 만들면 buildContext가 해당 State에 할당된다.
    • 모든 위젯은 bool this.mounted property 속성을 갖고 있고, buildContext가 할당되면 true가 된다.

화면 드로잉

  • initState()
    • 클래스 생성자 이후 위젯이 생성될 때 첫 번째로 호출되는 메서드.
    • initState는 한 번만 실행되며, super.initState()로 호출해야 한다.
@override
initState() {
  super.initState();
  // Add listeners to this class
  cartItemStream.listen((data) {
    _updateWidget(data);
  });
}
  • didChangeDependencies()
    • initState() 실행 후 호출되는 메소드.
    • 해당 위젯이 의존하는 위젯이 변경될 때도 호출된다. (Widget A가 Widget B를 상속받았는데 Widget B가 업데이트될 때 호출된다.)
  • build()
    • build()에서 위젯이 그려진다. (Render).
    • State 클래스는 반드시 오버라이딩 되어야 하는 함수이다. (만약 오버라이딩 되어 있지 않은 경우 에러)
    • 변경 사항이 있을 때마다 호출.
@override
Widget build(BuildContext context) {
   return Container(color:Colors.red);
}
  • didUpdateWidget()
    • 상위 위젯이 변경되어 해당 위젯을 동일한 런타임 내에서 재구성해야 할 때 호출된다. (Flutter는 오래 살아 있는 State를 재사용하기 때문이다.)
    • 이러한 경우 일부 데이터를 다시 초기화할 수 있다.
  • setState()
    • framework에게 State가 변경되었다는 것을 알리기 위해 사용된다. (통보해야만 framework가 build()를 호출한다.)
    • setState()는 필요할 때마다 호출해야 하기 때문에 비동기 콜백을 받지 않는다.
    • setState() 외부에서 상태를 변경하면 UI를 재구성하는 빌드 메서드가 트리거 되지 않으므로 변경 내용이 필요에 따라 반영되지 않습니다.

화면 파기

  • deactive()
    • State가 트리에서 제거될 때 호출된다. 그러나 현재 프레임이 완료되기 전에 재삽입될 수 있다.
    • State는 다른 트리로 이동할 수 있기 때문에 기본적으로 존재한다.
  • dispose()
    • State 객체가 제거되면 호출된다. (영구적)

 
참고자료 :
https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html

 

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

https://flutterbyexample.com/lesson/stateful-widget-lifecycle
https://velog.io/@threeplef/StatefulWidget-Lifecycle
https://medium.com/@rahulsharmadev/flutters-stateless-and-stateful-widget-lifecycle-cbecbed35c5
 

  •  
반응형