[Flutter] 생명주기

Jay·2024년 7월 30일

Flutter

목록 보기
8/12
post-thumbnail

생명주기가 중요한 이유 ‼️

  • 상태가 변하는 위젯이나 컴포넌트 등은 각 수명이 있는데 이것들을 잘 관리해야 UI를 유연하게 수행가능하다
  • 성능 최적화를 수행할 수 있다
  • 오류가 발생했을 때 적절한 조취를 취할 수 있다

즉, 앱의 성능과 직접적인 관련이 있기 때문에 생명주기를 잘 관리해줘야 하는 것이다


플러터에서는 widget의 생성부터 파기까지 위젯의 생명주기가 관리 되어지고 있고, 생명주기의 특정 시점에서 특정 메소드가 호출되어진다.

이러한 life cycle 의 상태를 이해함으로써 widget의 정교한 제어가 가능하다.

Life cycle은 각 위젯이 얼만큼의 시간동안 동작하는지 이해하기에 좋은 개념이


Life cycle 순서

  1. 화면 구축
  2. 재드로잉
  3. 화면파기

1. 화면 구축

createState()

  • statefulWidget에 반드시 존재해야 한다
  • statefulWidget을 구축하자마자 호출된다
  • 위젯 트리에 상태를 만들기 위해 호출된다
class ExampleWidget extends StatefulWidget {
  const ExampleWidget({Key? key}) : super(key: key);

  
  _ExampleWidgetState createState() => _ExampleWidgetState();
}

initState()

  • 위젯이 생성될 때 처음으로 호출되는 메서드로 위젯트리를 초기화 해준다
  • build() 코드 전에 작성되어야 한다.
  • stateful 에 해당하는 class에서 호출된다
  • 최초 단 한번만 호출된다
  • 주로 context에서 가져온 부모 요소에 의존하는 데이터나 API 통신을 통한 데이터를 감시, 감시할 때 많이 사용한다
// API 통신이나 부모요소에 의존하는 데이터일 경우
  
  void initState() {
    super.initState();
     data = 'Initial data';		// data 초기화
    // _counter = 0;  이 코드는 로컬변수이므로 아래처럼 사용하는 게 편리함
  }
  
// local 변수를 사용하는 경우 : initState() 굳이 안 사용해도 됨 
int _counter = 0; 

didChangeDependencies()

  • 위젯이 최초 생성된 후, initState() 다음에 호출된다
  • 위젯이 의존하는 데이터의 객체가 호출될 때마다 호출된다

void didChangeDependencies(){
  super.didChangeDependencies();
  /*state 변경 시 호출*/
}

2. 재드로잉

build()

  • 반드시 존재해야 한다
  • 위젯으로 만든 UI를 구축한다
  • 이곳에 계산이 필요한 로직이 많이 있다면 앱의 성능이 낮아진다 !!!!!
  • 다양한 곳에서 반복적으로, 가장 많이!!! 호출된다
  • 변경된 부분의 트리를 감지하고 대체한다
  • build() 메서드는 버튼을 누르거나 액션을 할 경우마다 호출되기 때문에 자주 호출된다
  • 반드시 widget을 return 해야 한다

Widget build(){
  return Container(...)
} 

didUpdateWidget()

  • 위젯의 구성이 변경될 때마다 호출된다
  • 부모 위젯이 변경되어서 다시 화면이 재구성 되어야 하는 경우에 호출된다
  • 이전 상태의 자기 자신을 받는다 : oldWidget

void didUpdateWidget(covariant T oldWidget) {
  super.didUpdateWidget(oldWidget);
  if(oldWidget.value != widget.value){
    print('update!');
  }
}

setState()

  • 상태가 변경되었을 때 framework 에 상태가 변경됨을 알리고, build() 가 호출된다
  • setState() 함수를 사용하지 않고 값을 변경시키는 경우, UI에 변경데이터가 반영되지 않는다
void setState(() => {
  _myState = value;
})

3. 화면 파기

dispose()

  • 객체가 트리에서 완전히 삭제되는 것
  • 즉, State 객체가 영구적으로 제거 된다는 뜻이다 (사용되었던 것 영구적 제거)
  • 더 이상 build 되지 않는 화면이라는 것
  • 불필요한 업데이트를 막을 수 있다
  • 제거해주지 않으면 메모리 누수가 발생하여 앱의 성능이 떨어진다

void dispose() {
  // ...
  super.dispose()
}

class _AppState extends State<App> {
  
  void initState() {
    super.initState();
    _counter = 0;
    print('init!');
  }

  
  void dispose() {
    super.dispose();
    print('dispose!');
  }

  
  Widget build(BuildContext context) {
    print("build!");
    return MaterialApp(
    ...

각 메소드를 설정하고 print 해보면 콘솔창에 라이프사이클이 출력되므로 확인하기 용이하다


state별 Lifecycle

1. statelessWidget( )

: 보여주기만 한다

위 사진 처럼 stateless 는 화면에 보여주기만 하는 build() 로 바로 넘어간다.
stateless내부적으로 상태를 가진다

하지만 less를 사용하는 이유 ?
변경불가한 상태를 가지는 widget이기 때문이다

2. statefulWidget( )

: 상태가 변하는 것까지 보여준다

statefulWidget은 상태라 변경가능한 widget이다

Stateful은 stack 구조이므로 이전 페이지로 이동가능한 것이다.

따라서 무수한 build() 가 쌓기면 시간이 오래 걸리며 성능이 떨어지게 되는 것이다
dispose() 를 통해 종료한다면, 순서에 맞게 Page3 부터 차례대로 종료될 것이다

profile
Live a life you will remember !

0개의 댓글