Widget 類別的原始碼上有標注 @immutable,這個標注的意思是不可變的;簡單的來說這個類別裡的類別屬性必需宣告成 final,經賦值後就不可改變。
@immutable
abstract class Widget extends DiagnosticableTree {
/// Initializes [key] for subclasses.
const Widget({ this.key });
...
在先前的範例中,我們有使用過 StatelessWidget,這類型的控件通常只需要定義佈局內容,而 StatefulWidget 內部使用 State 來處理狀態變化的管理,可以在收到異動後透過 setState 通知 Flutter 重新渲染畫面。
Widget 在設計上是 immutable 的,也就是說控件在經過創建後就不能夠修改,所以 Flutter 設計上將狀態管理的這件事情交由 State 類別來處理。
繼承 StatefulWidget 的控件需要覆寫掉 createState 這個方式,回傳自己定義的 State 對象,在 State 中,我們可以定義想要的屬性,並且定義控件 build 方法,這個方法與 StatelessWidget 的 build 行為一樣是用來定義佈局的內容。
StatefulWidget 的實作可以參考下面時間控件的寫法,在狀態中我們有個字串類別的 _now 屬性用來顯示目前的時間。TimeModel 類別 mixin ChangeNotifier,每隔一秒鐘就會觸發時間變更的事件。
我們在生命週期階段的 initState 監聽時間變更的事件,並在收到事件後更新_now的資料並呼叫setState更新畫面。
class Clock extends StatefulWidget {
// 這邊的 key 是底層 widget canUpdate 方法有關
const Clock({Key? key}) : super(key: key);
@override
_Clock createState() => _Clock();
}
class _Clock extends State<Clock> {
// TimeModel 自己實作的時間類別
// 此類別 mixin ChangeNotifier 類別,提供`觀察者模式`的特性
final TimeModel time = TimeModel();
String _now = "";
// 透過呼叫 setState 通知狀態已異動
_updateTime() {
setState(() {
_now = time.toString();
});
}
// State 生命週期
@override
void initState() {
print('====initState===');
super.initState();
// 監聽事件
time.addListener(_updateTime);
}
@override
Widget build(BuildContext context) {
print('====build====');
return Text(_now);
}
}
今日成果

重點回顧:
StatelessWidget 和 StatefulWidget 兩種。StatefulWidget,並定義 State 物件。setState 通知 widget