플러터는 3개의 Tree로 구성되어 있다.
위젯트리는 우리가 코드를 통해 구현한 트리를 의미한다.
우리는 코드를 통해 widget tree를 건들 수 있고, build가 실행되면 widget tree의 객체들이 사라지고,
새로운 widget tree가 다시 생겨난다.
위젯트리는 빠르게 생겨났다 사라지고 다시 빌드되지만 Element Tree는 widget Tree의 객체들이 처음생겨날 때 한 번 생겨난다. 앱이 start되거나 할 때 말이다.
이때 element Tree는 widget tree의 위젯들과 1:1로 연결되며, widget들의 정보를 담고 있는다.
element tree는 플러터가 내부적으로 만든다.
widget tree의 객체들이 사라지고 다시 빌드되면 그때 element tree는 widget tree의 새로 생겨난 위젯들과 1:1 매칭을 다시 연결하고(reference를 다시 연결), 그 뒤에 기존의 위젯과는 변경된 내용들이 없는지 체크한다.
변경된 사항들은 render tree에 전달되어서 해당 부분들만 다시 render하라고 말해준다.
각 위젯은 context를 갖고 있습니다. context는 위젯에 대한 meta정보나, 위젯트리에서의 위치를 나타내주는데요. Element Tree는 이 위젯에 대한 context로 구성되어 있습니다.
context는 위젯의 meta정보도 있지만, 위젯트리에서의 위치정보도 있기 때문에, 이것을 통해서 위젯들간의 위치를 정확히 파악할 수 있습니다. inherent widget에서는 context의 위치정보를 사용하여 다른 위젯들과 곧장 연결합니다.
MediaQuery나 Theme 같은 것들이 대표적인 inherent widget입니다. 얘네들을 사용할 때 우리는 of(context)를 통해 곧장 data에 접근합니다. 기존의 생성자 parameter를 통해 쭉 전달받은 것이 아니지요. 이것은 context를 통해 위젯트리 상단에 위치하는 MediaQuery나 Theme의 위치를 파악하여 직접 연결을 해서 정보를 가져오는 것입니다.
inherent widget(의존성을 주입)을 좀 더 쉽게 쓰는 데 Provider다.
만약 변경점이 생길 때마다 알려줘야 한다면 그때 사용하는 것이 ChangeNotifierProvider다.
ChangeNotifierProvider의 주입을 받을 수 있으려면 무조건 "extends ChangeNotifier"를 붙여줘야 한다.
Context가 하는 일이 무엇인지 알아두어야 합니다.
실제로 그려진 화면에 대한 Tree이다.
Element tree랑 연결되어 있으며 widget tree랑은 연결되어 있지 않다.
이 부분 역시 플러터가 알아서 관리한다.
이런 원리 때문에 build를 다시 해도, 객체만 만들어질 뿐 화면을 다시 구성하는 데에는 큰 영향을 주지 않는다.
이런 원리 때문에 플러터가 빠르고 효율적이기도 하다.
cf) Stateful Widget