1. 程式人生 > >【老孟Flutter】為什麼 build 方法放在 State 中而不是在 StatefulWidget 中

【老孟Flutter】為什麼 build 方法放在 State 中而不是在 StatefulWidget 中

![](https://img2020.cnblogs.com/other/467322/202101/467322-20210113213847858-1154453378.png) > **老孟導讀**:此篇文章是**生命週期相關文章**的番外篇,在檢視原始碼的過程中發現了這一有趣的問題,歡迎大家一起探討。 > > Flutter 中Stateful 元件的生命週期:[http://laomengit.com/blog/20201227/Stateful%E7%BB%84%E4%BB%B6%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.html](http://laomengit.com/blog/20201227/Stateful%E7%BB%84%E4%BB%B6%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.html) > > Flutter 中與平臺相關的生命週期:[http://laomengit.com/blog/20201227/%E7%9B%B8%E5%85%B3%E5%B9%B3%E5%8F%B0%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.html](http://laomengit.com/blog/20201227/%E7%9B%B8%E5%85%B3%E5%B9%B3%E5%8F%B0%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.html) > > 部落格中還有更多精彩文章,也歡迎加入 Flutter 交流群。 ### 靈活性 將 **build** 方法放在 State 中比放在 **StatefulWidget** 中更具靈活性,比如說,**AnimatedWidget** 是 **StatefulWidget** 的子類,AnimatedWidget 是一個抽象類,其中有一個 `Widget build(BuildContext context)` 的抽象方法,此方法需要子類重寫,AnimatedWidget 原始碼如下: ```dart abstract class AnimatedWidget extends StatefulWidget { ... /// Override this method to build widgets that depend on the state of the /// listenable (e.g., the current value of the animation). @protected Widget build(BuildContext context); /// Subclasses typically do not override this method. @override _AnimatedState createState() => _AnimatedState(); ... } ``` 刪除了一些程式碼,保留了重點程式碼。 試想一下,如果 build 方法放在 StatefulWidget 中,則 AnimatedWidget 中的 build 方法需要帶一個 State 引數,如下: ```dart abstract class AnimatedWidget extends StatefulWidget { ... /// Override this method to build widgets that depend on the state of the /// listenable (e.g., the current value of the animation). @protected Widget build(BuildContext context, AnimatedState state); /// Subclasses typically do not override this method. @override _AnimatedState createState() => _AnimatedState(); ... } ``` 但 AnimatedState 是內部實現,並不需要開放給外部(開發者),外部也不需要知道 AnimatedState 的內部實現。 ### 閉包 this 指向異常 假設 build 方法在 StatefulWidget 中,StatefulWidget 的子類寫法如下: ``` class MyWidget extends StatefulWidget { final Color color; @override Widget build(BuildContext context, MyWidgetState state) { print('${this.color}'); return Container(); } } ``` 此時的 **this** 指向的是 MyWidget 的例項,然後父元件改變顏色,重新構建 MyWidget 元件,前一個 MyWidget 的例項中的 **this** 依然指向前一個 MyWidget 的例項,顏色並未發生變化。 如果 build 方法在 State 中,程式碼如下: ```dart class MyWidget extends StatefulWidget { final Color color; const MyWidget({Key key, this.color}) : super(key: key); @override _MyWidgetState createState() => _MyWidgetState(); } class _MyWidgetState exten