Flutter Stateful Widget 라이프 사이클 - 1. 생성자

플랙트·2021년 3월 31일
0

아래는 머터리얼(Material) 라이브러리의 체크박스 위젯을 사용하여 체크박스를 화면에 그린 예제이다.

체크박스는 대표적인 stateful widget이다. 이해를 돕기 위해 체크박스를 이용해 stateful widget 라이프사이클을 설명해 보자.

1. 생성자(constructor)

나는 플러터 내부 구조는 아직까지 잘 모른다. 하지만 위젯도 어쨋든 객체이므로 생성자가 있다. 생성자를 통해 위젯이 가질 속성(property)을 넘겨준다.

아래는 build 메소드에서 체크박스 생성하는 부분이다. 여기서 생성자가 호출한다.

  생략...
 
  bool _value1 = false;

  
  Widget build(BuildContext context) {
  	// 생성자가 호출된다.
    return Material(
      child: Checkbox(value: _value1, onChanged: (value) {
        setState(() {
          _value1 = value;
        });
      }),
    );
  }
  생략...

MaterialApp 위젯의 생성자를 호출하여 리턴한다. 또한 생성자의 child 매개변수(parameter)는 다른 위젯 타입이다. 이 때 다시 체크박스 위젯의 생성자를 호출하여 체크박스 위젯을 넘겨주고 있다. 체크박스 위젯의 생성자에서는 value라는 이름있는 매개변수(named parameter)를 통해 체크박스의 선택 여부를 결정한다. onChanged 매개변수로는 체크박스 위젯의 내부 상태가 바뀌었을 때의 이벤트를 처리하는 콜백함수(callback)을 넘겨주고 있다.

이처럼 위젯의 생성자를 통해 우리는 그 위젯의 속성(성질)이나 초기 상태 등을 정할 수 있다. 이는 위젯의 재사용성을 위해 핵심 적인 부분이다. 만약에 우리가 생성자로 위젯의 속성을 넘겨줄 수없다면, 우리는 위젯의 생이나 모양 하나를 바꿀 때에도 매 번 새로운 위젯을 생성해야 할 것이다.

생성자니 라이프 사이클이니 해서 괜히 어렵게 생각할 수 있지만, 우리가 이미 다 알고 있는 내용이다. 괜히 쫄지 말자.

체크박스 위젯 내부의 생성자 선언부는 다음과 같다.

class Checkbox extends StatefulWidget {
  // 생성자 선언부
  const Checkbox({
    Key key,
     this.value,
    this.tristate = false,
     this.onChanged,
    this.mouseCursor,
    
    중략...
    
    this.autofocus = false,
  }) : assert(tristate != null),
       assert(tristate || value != null),
       assert(autofocus != null),
       super(key: key);
       
       
  // 위젯 클래스 멤버 변수 선언부     
  final bool value;
  final ValueChanged<bool> onChanged;
  final MouseCursor mouseCursor;
... 생략

눈에 띄는 것은 체크박스 위젯 클래스가 StatefulWidget이라는 부모 위젯을 extends 키워드로 상속받고 있다는 점이다. 따라서 CheckBox Widget은 Stateful Widget이다.

class Checkbox extends StatefulWidget 
 ... 생략

생성자 선언부를 보자. 일반 함수를 정의하는 것과 비슷하게 생겼다. 이 함수가 생성자임을 알 수 있는 이유는 클래스명과 같은 함수명을 가졌기 때문이다. 생성자는 일종의 클래스를 생성하는 특수한 함수이다.(엄밀하게 생각했을때 맞는 말인지는 잘 모르겠다.)

  const Checkbox({
    Key key,
     this.value,
    this.tristate = false,
     this.onChanged,
    this.mouseCursor,
    
    중략...
    
    this.autofocus = false,
  }) 

생성자의 중요한 역할은 클래스 멤버 초기화이다. 아래쪽에 선언된 클래스 멤버 변수를 생성자에서 초기화한다. 위에서 처럼 생성자의 매개변수 선언부에서 "this.value" 와 같은 형식으로 멤버 변수를 참조하면 value 멤버를 해당 매개변수값으로 초기화한다.

생성자의 매개변수 선언부를 살펴보자.

@required가 앞에 붙어있으면, 해당 속성은 생성자를 호출할때 꼭 매개변수로 넘겨주어야 한다.
"this.tristate = false" 라는 구문은 생성자 호출 시 tristate 매개변수로 아무것도 넘겨주지 않아도 기본값으로 false를 사용한다는 뜻이다. 생성자에서 호출 시 값을 넘기지도 않고 기본값도 없는 필드는 기본적으로 null이 넘어온 것과 같이 취급한다.

생성자 아래 assert문은 debug 모드에서 괄호 안의 식이 거짓인 경우 에러를 발생시킨다. 따라서 치명적인 오류를 조기에 발견할 수 있도록 돕는다. assert문에 따르면 tristate는 null이 될 수 없다.

생성자를 정의할 때 가장 중요한 점은 이 위젯을 생성할때 어떤 속성이나 로직을 외부에서 주입 해주어야 하냐는 것이다. 일반적으로 해당 위젯에서 변경되어질수 있는 로직이나 속성들은 함수나 값의 형태로 외부에서 주입되어야 한다. 예를 들어 Container 위젯에서 container를 렌더링 하는 로직은 contaner 위젯 내부의 변경되지 않는 로직이므로 주입되지 않아도 되지만, gestureDetector에서 tap event가 발생했을때 tap을 처리하는 로직은 GestureDtector 위젯 인스턴스마다 다를 수 있으므로 외부에서 주입되어야 한다. 이처럼 생성자는 위젯의 재사용성의 핵심이다.

[다음 편에 계속...]

[reference]
1. Life cycle in flutter

profile
유용한 서비스에 관심이 많은 flutter 개발자입니다.

0개의 댓글