# Flutter State Management ### StatefulWidget vs StatelessWidget * **StatelessWidget**: 無狀態 widget,在 `build` 函數返回一個 widget,建構一次後就不會再呼叫此函數,需要參數時放在建構子內,用 class level property 存取後可在 `build` 函數內使用。 * **StatefulWidget**: 有狀態 widget,在 `createState` 返回一個包含一個 widget 的 State,需要參數時放在建構子內,用 class level property 存取後可在 `State` 類別內使用。 * **State**: 一個抽象類別並只接收一個 `StatefulWidget` 參數,在 `build` 函數返回一個 widget,需要參數時可透過 `widget.XXXproperty` 取得 `StatefulWidget` 內的屬性,資料更動需要刷新界面時呼叫 `setState` 就會透過 `build` 函數重新渲染。 ### Widget 之間如何傳遞資料 ``` ParentWidget extends StatelessWidget( children:[ AWidget(), BWidget(), ... ] ) AWidget extends StatefulWidget( int valueA = 0; @override State<AWidget> createState() => _AWidgetState(); ) class _AWidgetState extends State<AWidget> { @override Widget build(BuildContext context) { return ...( Text('valueA = $valueA'); ... onPress() { setState(() { valueA ++; }); } ) } } BWidget extends StatefulWidget( int valueB = 0; @override State<BWidget> createState() => _BWidgetState(); ) class _BWidgetState extends State<BWidget> { @override Widget build(BuildContext context) { return ...( Text('valueB = $valueB'); ... onPress() { setState(() { valueB ++; }); } ) } } ``` 以上是 `AWidget` 顯示 valueA,`BWidget` 顯示 valueB,並各自管理 state。 **Q:如何做到 `AWidget` 顯示 valueA + valueB,`BWidget` 也顯示 valueA + valueB?** **A:** 把需要共用的 value 存在父 widget,經由父 widget 將參數傳遞下去。 子 widget 在需要 value 改變時透過 callback 回到父 widget 改變 value 並呼叫 `setState` 重新渲染 UI。 ``` ParentWidget extends StatefulWidget( @override State<ParentWidget> createState() => _ParentWidgetState(); ) class _ParentWidgetState extends State<ParentWidget> { int valueA = 0; int valueB = 0; @override Widget build(BuildContext context) { return children:[ AWidget(valueA, valueB, addValue(){ setState(() { valueA++; }); } ), BWidget(valueA, valueB, addValue(){ setState(() { valueB++; }); } ), ... ] } } AWidget extends StatelessWidget( final Function() addValue; const AWidget({super.key, required this.onSelect}); @override Widget build(BuildContext context) { return ...( Text('valueA = $valueA, valueB = $valueB'); ... onPress() { addValue(); } ) } ) BWidget extends StatelessWidget( final Function() addValue; const BWidget({super.key, required this.onSelect}); @override Widget build(BuildContext context) { return ...( Text('valueA = $valueA, valueB = $valueB'); ... onPress() { addValue(); } ) } ) ``` 以上是 `AWidget` 顯示 valueA + valueB,`BWidget` 顯示 valueA + valueB,並可以交互影響。 ***注意前後寫法各自 widget 繼承的是 StatefulWidget 或是 StatelessWidget?為什麼?***