iT邦幫忙

2022 iThome 鐵人賽

DAY 11
0
Mobile Development

通徹 Flutter 學習路徑系列 第 11

通徹 Flutter 學習路徑 Day 11 - 奪回失去的狀態管理

  • 分享至 

  • xImage
  •  

狀態管理是在 Flutter 中很重要的一環
然而在先前的文章中被我給省略掉了 Orz
那我們今天就先把這失去的一章給取回吧!!


在 Flutter 中 Widget 被分為兩種類別
一種是 Stateless Widget 而另一種則是 Stateful Widget
簡而言之, Stateless Widget 的狀態及相關設定屬性等會在 build 的時間點被確定下來
因此在 build 後這些屬性是無法再被修改的。

而對比之下,Stateful Widget 則具備 build 後修改內部屬性的特性。
因此可以透過對內部狀態的更換及修改
來達到 Widget 行為的變更!
然而在建立 Stateful Widget 時會額外需要 State<T> 這個 Widget
這兩個 Widget 拆開來的最大原因便是因為效率


StatefulWidget 生命週期

以下內容來自參考資料的 StatefulWidget Lifecycle | Flutter by Example 一文
根據篇幅及內容複雜度有刪去一定程度的內容
有興趣的讀者可以再多加閱讀

  • createState()
    當 Flutter 建置 StatefulWidget 時,便會立即呼叫此函式。

  • mounted == true
    當 createState 創立完畢後,buildContext 便會被分配給這個 Widget。
    而 BuildContext 簡而言之就是對應到 Widget Tree 上放置這個 Widget 的位置。
    每個 Widget 都擁有這個屬性,當被分配到 buildContext 時則會將此屬性設定為 true

    tips:
    可透過判斷元件是否被 mounte 了,來判斷是否可以呼叫 setState()
    ex.
    dart if(mounted){ setState(...)

  • initState()
    當 Widget 被創立時第一個呼叫的函式。
    initState 只被"呼叫一遍並且僅有一次"。
    必須連帶的呼叫 super.initState()。

    @override

    1. 初始化那些與特定 BuildContext 有關的資料
    2. 初始化那些與父層相關的屬性
    3. 訂閱 Streams, ChangeNotifier 或其他可以改變這個元件的資料。
    @override
    initState() {
       super.initState();
       // Add listeners to this class
      cartItemStream.listen((data) {
        _updateWidget(data);
      });
    }
    
  • didChangeDependencies()
    在 initState 被呼叫後立即呼叫的函式。
    如果所依賴的 InherotedWidget 更新了此函式也會被呼叫。
    而 build 必然會在 didChangeDependecies 被呼叫後才會呼叫。

  • build()
    最常被呼叫的方法 XDD
    呼叫時必須回傳 Widget 以供渲染。

  • didUpdateWidget()
    此函式在上層的 Widget 更改時並且需要重新建置此 Widget 時會被呼叫。
    這個函式會在 build 完成後才會被呼叫,因此在之中用 setState 是無效的。

  • setState()
    時常被開發者以及 Flutter 框架所呼叫。
    用來告知 Flutter 說 "資料已被修改!",並且 buildContext 會被要求重新建置。

  • deactivate()
    鮮少用到。
    當 State 被從樹中移除時會進行呼叫。

  • dispose()
    當 State 被永久移除時會被呼叫。

  • mounted == false
    該 State 將無法被 remount。


以下我們來列出 Stateless Widget 及 Stateful Widget 的使用範例 ~

Stateless Widget

class Frog extends StatelessWidget {
  const Frog({
    super.key,
    this.color = const Color(0xFF2DBD3A),
    this.child,
  });

  final Color color;
  final Widget? child;

  @override
  Widget build(BuildContext context) {
    return Container(color: color, child: child);
  }
}

Stateful Widget

class Bird extends StatefulWidget {
  const Bird({
    super.key,
    this.color = const Color(0xFFFFE306),
    this.child,
  });

  final Color color;
  final Widget? child;

  @override
  State<Bird> createState() => _BirdState();
}

class _BirdState extends State<Bird> {
  double _size = 1.0;

  void grow() {
    setState(() { _size += 0.1; });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: widget.color,
      transform: Matrix4.diagonal3Values(_size, _size, 1.0),
      child: widget.child,
    );
  }
}

參考資料

強而有力的官網後盾 - Stateful Widget
強而有力的官網後盾 - Stateless Widget
Flutter 生命週期+基本觀念介紹
Flutter Design Patterns: 6 — State
StatefulWidget Lifecycle | Flutter by Example


上一篇
通徹 Flutter 學習路徑 Day 10 - 來仿造一個 Messenger 吧!(1)
下一篇
通徹 Flutter 學習路徑 Day 12 - 來仿造一個 Messenger 吧!(2)
系列文
通徹 Flutter 學習路徑30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言