Flutter Widget life-cycle

강정우·2024년 12월 19일
0

Flutter&Dart

목록 보기
88/88
post-thumbnail

생명주기(Lifecycle)란?

생명주기는 앱이나 앱의 각 화면이 생성되고 소멸될 때까지의 과정을 의미한다. 대부분의 UI 프레임워크나 라이브러리는 컴포넌트의 생성, 업데이트, 소멸 등의 단계를 가지고 있으며, 이런 단계를 생명주기 메소드라고 부른다.

하지만 Flutter 에는 명시적인 "Life-Cycle"이라는 개념이 존재하지 않는다.
다만, 위젯의 상태 변화와 관련된 StatefulWidget 의 생명 주기가 일반적인 생명 주기처럼 동작한다.
특히 Flutter에서 상태 관리위젯 트리를 업데이트하는 방식이 생명 주기의 중요한 부분이다.

StatefulWidget 의 생명 주기 단계

StatefulWidget 은 State객체와 연결되어 있으며, 이 State객체에는 다음과 같은 생명 주기 메서드가 포함되어 있다.

createState()

StatefulWidget을 생성하면 호출되며, 상태 관리용 객체를 생성한다.

class MyStatefulWidget extends StatefulWidget {
  
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

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

📑 설명

StatefulWidget이 처음 생성될 때 호출되며, 위젯의 상태를 관리하는 State 객체를 생성

🛠 특징

이 메서드는 위젯마다 한 번만 호출.

⚙ 사용 예시

상태 초기화 및 State 클래스와 연결.
State객체 _MyStatefulWidgetState 를 생성하고 반환.

initState()

initState는 위젯이 생성될 때 한 번만 호출되며
초기화 작업(예: 변수 초기화, 데이터 로드, 이벤트 리스너 설정 등)을 수행.
플러터에 의해 실행되며 StatefulWidget의 2번째 클래스의 super class인 State객체가 생성될 때 실행된다.

class MyStatefulWidget extends StatefulWidget {
  
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  String _message = "";

  
  void initState() {
    super.initState();
    _message = "Hello, Flutter!";
    print("initState called: $_message");
  }

  
  Widget build(BuildContext context) {
    return Center(
      child: Text(_message),
    );
  }
}

📑 설명

State 객체가 생성된 후 한 번 호출됨. 상태 초기화나 API 호출 같은 1회성 작업을 수행할 때 유용함.

🛠 특징

super.initState()를 반드시 호출해야 됨.

⚙ 사용 예시

초기 데이터를 로드하거나 Stream 또는 Controller를 설정할 때.

didChangeDependencies()

위젯이 의존하는 InheritedWidget 이 변경되었을 때 호출된다.
초기화 직후에도 호출된다.

class MyStatefulWidget extends StatefulWidget {
  
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  
  void didChangeDependencies() {
    super.didChangeDependencies();
    print("didChangeDependencies called");
  }

  
  Widget build(BuildContext context) {
    return Text('Check console for logs.');
  }
}

📑 설명

위젯이 의존하는 InheritedWidget이 변경되었을 때 호출.

🛠 특징

State가 생성된 직후에도 호출.

⚙ 사용 예시

Theme 또는 Locale 같은 외부 의존성이 바뀔 때 반응.

build()

위젯의 UI를 구성하는 핵심 메서드로, 상태가 변경될 때( setState에 의하여 실행될 때 )마다 호출.
혹은 Widget이 처음 build함수가 실행될 때 호출

class MyStatefulWidget extends StatefulWidget {
  
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int _counter = 0;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Build Example")),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("Counter: $_counter"),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  _counter++;
                });
              },
              child: Text("Increment"),
            ),
          ],
        ),
      ),
    );
  }
}

📑 설명

버튼을 클릭할 때마다 화면이 업데이트되며 build()가 호출.

🛠 특징

이 메서드는 화면을 다시 그리는 데 사용된다.

⚙ 사용 예시

상태를 기반으로 화면을 그릴 때.

didUpdateWidget()

부모 위젯이 변경되었을 때 호출.
WidgetsBindingObserver를 통해서도 호출 가능.

class MyStatefulWidget extends StatefulWidget {
  final String title;

  MyStatefulWidget({required this.title});

  
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  
  void didUpdateWidget(covariant MyStatefulWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget: ${oldWidget.title} -> ${widget.title}");
  }

  
  Widget build(BuildContext context) {
    return Text(widget.title);
  }
}

📑 설명

부모에서 title을 변경하면 호출.

🛠 특징

이전 위젯과 새 위젯의 차이를 확인하고 작업을 수행함.

⚙ 사용 예시

위젯의 프로퍼티가 변경되었을 때 작업이 필요할 경우. (사용 예시)

setState()

상태가 변경되었음을 Flutter에 알리고, UI를 재구성하도록 트리거.

class MyStatefulWidget extends StatefulWidget {
  
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  String _message = "Hello";

  void _updateMessage() {
    setState(() {
      _message = "Hello, World!";
    });
  }

  
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(_message),
        ElevatedButton(
          onPressed: _updateMessage,
          child: Text("Update Message"),
        ),
      ],
    );
  }
}

📑 설명

버튼을 클릭하면 메시지가 "Hello, World!"로 변경됨.

🛠 특징

이 메서드는 직접 호출해야 하며, build()를 다시 호출하도록 요청합니다.

⚙ 사용 예시

버튼 클릭, API 응답 등을 통해 화면을 업데이트할 때.

deactivate()

class MyStatefulWidget extends StatefulWidget {
  
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  
  void deactivate() {
    super.deactivate();
    print("deactivate called");
  }

  
  Widget build(BuildContext context) {
    return Container();
  }
}

📑 설명

위젯이 위젯 트리에서 제거될 때 호출됨.

🛠 특징

특정 위젯이 더 이상 사용되지 않음을 나타냄.

⚙ 사용 예시

자식 위젯이 변경될 때, 이를 감지.
탭 전환이나 위젯 트리 변경 시 호출됨.

dispose()

Widget이 삭제되기 전에 실행. OR WidgetsBindingObserver를 통해 conditionally 하게 렌더링 된다든지 할 때도 사용.

class MyStatefulWidget extends StatefulWidget {
  
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  late TextEditingController _controller;

  
  void initState() {
    super.initState();
    _controller = TextEditingController();
  }

  
  void dispose() {
    _controller.dispose(); // 메모리 누수 방지
    print("dispose called");
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return TextField(controller: _controller);
  }
}

📑 설명

State 객체가 영구적으로 제거되기 전에 호출됨.

🛠 특징

Controller 해제, Stream 구독 취소, 메모리 정리를 수행함.

⚙ 사용 예시

TextEditingController, AnimationController 등을 정리할 때.

생명 주기 메서드 간 호출 순서 정리

  1. createState()
  2. initState()
  3. didChangeDependencies()
  4. build()
  5. didUpdateWidget() (필요 시 호출)
  6. deactivate()
  7. disspose()

위 메소드들은 프레임워크나 라이브러리에서 자동으로 호출되며, 우리는 이 메소드를 오버라이드하여 각 단계에서 수행할 작업을 정의할 수 있다.

StatelessWidget의 경우

StatelessWidget은 상태가 없기 때문에 단순히 build() 메서드만 호출됨.

StatelessWidget의 생명 주기

  1. 위젯 생성
  2. build() 호출
  3. 위젯 트리에서 제거

Flutter Life-Cycle이 중요한 이유

  • 리소스 관리: dispose()를 사용해 메모리 누수를 방지.
  • 상태 초기화: initState()에서 초기 상태를 설정.
  • 효율적인 UI 업데이트: setState()와 build()를 통해 필요한 부분만 다시 렌더링.
profile
智(지)! 德(덕)! 體(체)!

0개의 댓글