바뀔 때마다 위젯을 다시 렌더링해야 하는 위젯 데이터
StatelessWidget도 데이터를 지닐 수 있지만, 이런 데이터는 위젯이 살아 있는 동안 바뀌지 않거나 바뀌어도 화면에 영향을 주지 않는다.
플러터가 제공하는 상태를 지니는 위젯
항상 Widget 클래스와 상태 클래스, 두 개로 이뤄진다.
위젯 클래스는 다른 위젯 안에 배치되므로, 퍼블릭이어야 한다.
상태 클래스는 상태 데이터를 정의하고 유지한다.
화면에 위젯을 그리는 방법이 들어있는 build 메서드를 정의한다.
데이터 수집 또는 이벤트 처리에 필요한 콜백 함수를 정의한다.
상태 값은 상태 클래스 안에서 바꿔야 한다.
클래스를 둘로 나눠야 하는 이유는 두가지다.
첫번째, 역할과 책임을 분업화한다. UI와 상태 관리의 분리를 강제하는 플러터의 특성이다.
두번째는 성능이다. 프로세서에 두 가지를 따로 처리할 수 있게 만든다.
만약 하나의 클래스로 이루어진다면, 상태가 바뀌더라도 UI를 다시 그릴 필요가 없을 때도 다시 그려야 한다.
플러터는 다시 그려야 할 위젯이 있으면 위젯을 아예 새로 생성한 뒤에 그린다. 메모리에 있던 기존 위젯은 더 필요가 없으므로 가비지 컬렉션에 의해 사라진다. 하지만 문제는 위젯을 다시 그리기 위해 여전히 상태가 필요하다는 것이다. 플러터가 기존 상태 객체를 유지한다면 가비지 컬렉션으로 없앤 뒤에 다시 만들지 않고 그냥 다시 사용할 수 있다.
MVC 패턴에서 Controller의 역할
UI는 이벤트를 발생시키고, Bloc은 state를 UI에 전달한다.
BLoc에서 각 UI 객체 들은 Stream을 이용해서 BLoc 객체를 구독하고 있다.
BLoC 객체의 상태가 변경되면, BLoC 의 상태를 구독중인 UI 객체 들은 그 즉시 해당 상태로 UI 를 변경한다.
Inherited 위젯을 기반으로 한 상태 관리 패키지
상태를 생산하는 영역을 Provider, 소비하는 영역을 Consumer
ChangeNotifier : 변화를 알려주는 역할
여러 개의 Provider를 사용할 수 있게 MultiProvider 사용
return Center(
child: Text(
Provider.of<CounterProvider>(context).count.toString(),
),
);
위와 같이도 사용할 수 있지만, 이렇게 사용하면 state가 바뀔 때 마다 위젯 전체가 바뀌어지기 때문에 여러 효과나 연산이 많이 있는 위젯일 경우는 Consumer를 사용하는 것이 좋다.
return Center(
child: Consumer<CounterProvider>(builder: (context, provider, child) {
return Text(
provider.count.toString(),
);
}),
);