이름에서 알 수 있듯이 상태 유무에 차이가 있다.
내부 상태를 가지며 이를 추적한다. State와 Widget, 두 개의 클래스로 구성된다. Widget 클래스가 build 메서드를 가지고 있지 않고 모든 State 클래스가 build 메서드를 가지고 있다.
class _MyHomePageState extends State<MyHomePage> {
int _counter = 100;
void _incrementCounter() {
setState(() {
_counter--;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
객체의 상태와 관련이 있다. 이 메서드는 void Callback 형식의 인수 하나를 갖는다. setState를 호출하면 build 메서드를 실행하면서 설정이 바뀐 모든 위젯을 다시 그린다. 비동기로 사용할 수 없기 때문에 필요한 데이터가 모두 준비되어 있어야 한다.
위젯이 트리에 마운트되면 호출된다. 플러터가 화면에 위젯을 그리기 전에 필요한 모든 초기화를 State.initState에서 수행한다. 밑에 있는 생명주기처럼 initState는 상태 객체를 만들 때 한 번 호출된다.
위젯 생명주기 동안 내부 상태를 갖지 않는다. 또한 설정이나 자신이 표시하는 데이터를 신경 쓰지 않는다. 부모 위젯이 설정을 전달하거나 위젯 내부에서 설정(configuration) 정보를 전달할 수는 있지만 변경을 할 수 없다. 즉, 상태를 바꿀 수 없는 위젯이다.
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Test',
theme: ThemeData(
primarySwatch: Colors.amber,
),
home: const MyHomePage(title: 'Flutter Test App'),
);
}
}
전체 위젯 트리를 추적하는 것과 관련이 있으며 특히 트리에서 위젯의 위치와 관련이 있다. 위젯의 모든 build 메서드는 위젯 트리에서 위젯의 위치를 참조하는 BuildContext 하나를 인수로 받는다. 앞에서 봤던 카운터 앱을 기준으로는 Theme.of(buildContext).primaryColor를 호출해 위젯의 색을 바꿨다. 이 메서드는 트리의 현태 위치에서 Theme 정보를 얻은 다음 Theme 클래스의 primaryColor에 저장된 정보를 반환한다.
모든 위젯은 자신만의 BuildContext를 가지며, 한 위젯이 다양한 테마를 반환하게 만들어 한 트리에 여러 테마를 적용할 수 있다.
BuildContext는 특정 위젯을 정확하게 어떻게 표현할지 결정한다. 예를 들어 플러터는 BuildContext를 이용해 모달(Modal)과 라우트(Route)를 표시한다.BuildContext는 위젯 자체의 정보가 아니라 위젯 트리에서 위젯의 위치 정보를 포함한다.
자식들을 Row(행), Column(열)로 배치할지를 결정한다. 부모가 전달한 제약 조건에 따라 최대한의 공간을 차지하기 때문에 무한 사이즈 오류가 나지 않도록 주의가 필요하다.
실제 화면에 그리는 작업을 담당한다. 프레임워크 내부에서 이 클래스를 구현하며 모든 렌더 객체가 모여 렌더 트리(Render Tree)를 만든다. 렌더 객체는 각자 대응하는 위젯을 갖는다. 위젯 개발자들은 렌더 객체에 제약 조건 같은 데이터를 제공한다.
렌더 객체는 상태나 로직을 포함하지 않는다. 명령을 따르는 객체다.
위젯은 build 메서드에서 자식 메서드를 만들 수 있는데, 트리의 최하단에 렌더 객체를 만드는 RenderObjectWidget가 있다.
렌더 객체는 레이아웃 제약조건과 긴밀하게 연결되어 있다.
제약 조건 위젯으로 위젯의 제약 조건을 설정하면 렌더 객체가 최종적으로 프레임워크에게 위젯의 실제 물리적 크기를 전달한다.