티스토리 뷰

보통 안드로이드 개발을 하다 플러터를 접하게 되면 가장 먼저 찾아보는 개념이 LifeCycle이다. 

안드로이드에서는 Activity나 Fragement의 LifeCycle과 상태 변화에 따라 적절한 함수들이 호출된다.  이 함수들을 잘 이용해서 상황에 맞는 프로그램을 기능들을 추가하게 되는데  플러터에서도 이와 유사한 개념이 없을까 하고 찾아보게 된다.

이때 가장 먼저 접하게 되는 정보들이  StatefulWidget의 Lifecycle일것이다. 

StatefuleWidget LifeCycle

위 다이어그램만 보면 StatefulWidget에 그럴듯한 LifeCycle이 있는것 처럼 보인다. 

하지만 정확히 이야기 하자면 StatefulWidget은 LifeCycle을 가질 수  없다.  왜냐 하면 모든 Widget은 Immutable 하며 build과정에 항상 새롭게 생성되기 때문이다.

<StatefuleWidget과 State>

 

결국 StatefulWidget의 LifeCycle은 State의 LifeCycle이 되는데 State도 StatefulElement의 LifeCycle에 직접적인 영향을 받기 때문에  LifeCycle에 대해서 이야기하려면 Widget이 아닌 Element의 LifeCycle를 알아야 한다.

 

Element의 LifeCycle

Element는 아래와 같이 부모 Element에 의해 생성/재사용/제거 된다. 
이 과정은 ElementTree에 mount/unmount 되거나 rebuild 되는 것을 의미한다. 

 

ParentElement - UpdateChild  

우선 부모 Element에서 부터 시작해 보자 부모 element는 build 될 때 자신의 자식도 buld 되도록 해야 하므로 updateChild을 호출해서 자식들이 빌드 되도록 해야한다.

이때 자식 Element를 새롭게 생성해서 mount거나, 기존에 이미 사용하던 element 재사용 하기도한다.

Element의 생성

1.  생성 / mount() 
     부모 element는 자식 element가 재사용 가능한지 확인 후 재사용이 불가능할 경우  새로운 Element를 생성한 후 Mount 한다. 

final child = newWidget.createElement();
child.mount(this, slot);

// mount될때 _firstBuild가 수행된다.
@override
void mount(Element? parent, Object? newSlot) {
  super.mount(parent, newSlot);
  _firstBuild();
}

2. _firstBuild()  : 최초 빌드되기 전 

 Element가 처음 mount 된 후 빌드되기 전에 호출되는 함수로 Element가 첫 빌드되기 전에 수행해야 하는 로직이 있을 경우 하위 구현체(StatelessElement / StatefulElement 등)에서 추가 동작을 구현해 주고 있다.

// mount된 element는 _fristBuild를 호출해 자신의 첫 빌드를 수행한다. 
// _firstBuild()는 
_firstBuild()


// StatefulElement의 _fisrstBuild()와 build()
// state의 초기함수들을 호출한 후 state의 build를 호출함
@override
void _firstBuild() {
  state.initState();
  state.didChangeDepencencies();
  super._firstBuild();
  // _firstBuild를 호출하면 아래 함수들이 호출됨
  // _firstBuild()-> rebuild() -> performRebuild() -> build()
}
@override
Widget build() => state.build(this);



// StatelessElement의 _firstBuild()와 build()
// 별도의 동작없이 widget의 build를 호출함 
@override
void _firstBuild() {
  super._firstBuild();
  // _firstBuild를 호출하면 아래 함수들이 호출됨
  // _firstBuild()-> rebuild() -> performRebuild() -> build()
}

@override
Widget build() => widget.build(this);

 

 Element의  재사용

element의 재사용 가능 여부를 확인  (Widget.canUpdate) 후 재사용이 가능한 경우 


1. update()
element의 update함수를 호출한다. 
이 함수는 내부적으로 rebuild를 호출해서 element가  다시 빌드되도록 한다. 

 

 Element  제거와 소멸 

더 이상 사용하지 않는 child element는 이제 element tree에서 제거되어야 한다.  

 

1. deactivate()

build 과정에  _InactivateElements객체에 불필요한 element들을 추가하게 되는데
여기에 추가되는 시점에 element은 deactivate 된다. 

2. unmount()

위 과정에서  _InactivateElements에 모아 둔 deactivate된 element을 build마지막 과정에 

모두 unmount 하게 되며, element는 더 이상 사용할 수 없는 상태가 되어 소멸하게 된다. 

 

State의 LifeCycle은 Element LifeCycle의 그림자다. 

위에서 element의 생성, 재사용, 소멸 과정을에 대해서 간단하게 알아보았다. 

사실 lifecycle이 복잡하지 않지만 여러 element구현체들에서 추가 기능이 포함되면서 조금 더 복잡한 내부 과정을 가지게 된다.

특히 우리가 잘 알고 있는 state의 LifeCycle의 경우 StatefulElement에서 Element의 함수들을 재정의 해서 사용하고 있는데 

Element LifeCycle과 State LifeCycle을 연결시켜 보면 Element와 State의 관계를 좀더 명확하게 알수 있다.

 

 

마치며 

Widget Immutable하기 때문에 LifeCycle을 가질 수 없습니다. 그리고 StatefulWidget의  State 역시 LifeCycle을 가지는 것처럼 보이지만 사실은 Element LifeCycle의 그림자입니다. 

만약 개발 중 원치 않는 동작이 발생하거나 Element(state)가 재사용되지 않고 항상 생성되어 속도 저하가 발생한다면 위 과정을 한 번쯤 생각해 보시고 Element를 재사용할 수 있는 형태로 Widget들이 구성되어 있는지 살펴볼 필요가 있습니다.

 

 

-> 3부 GlobalKey와 LocalKey 에서 계속

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함