Flutter:介面重新整理和生命週期

CoorChice發表於2019-04-06

目錄傳送門:《Flutter快速上手指南》先導篇

在 Flutter 中,有兩類常用的 Widget:

  • 無狀態的 StatelessWidget

  • 有狀態的 StatefulWidget

在開發過程中,我們經常需要繼承它們兩來實現自己的 Widget。

1. StatelessWidget

一個 StatelessWidget 是不能被改變的,比如:IconText等。

如果你的控制元件一旦顯示,就不需要再做任何的變更,那麼你應該使用 StatelessWidget

實現一個自己的 StatelessWidget 很簡單。

當你看到下面這個例子?時,你就知道它有多簡單了。

class MyWidget extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return _buildMyWidget(context);
  }
複製程式碼

看,只要在 build() 中返回你的檢視就可以了。

2. StatefulWidget

一個 StatefulWidget 是有狀態的,可變的。

它可以改變自己的外觀,以響應使用者的操作或者資料的變化。

比如:CheckBoxSwitch..

我們之所以能夠改變一個 StatefulWidget,是因為它有一個設定狀態的函式:

setState((){
    // 更新狀態、資料
})
複製程式碼

呼叫這個函式後,就會觸發 StatefulWidget 的檢視樹重建。

因此,當我們需要一個可互動的,即能根據使用者操作或資料變化而改變檢視的 Widget 時,那就得用上 StatelessWidget 了。

2.1 自定義 StatefulWidget

現在,來建立一個自定義的 StatefulWidget:

  1. 實現一個 StatefulWidget,它是 Widget 的外層。

    class FavoriteStatefulWidget extends StatefulWidget {
    
      // 必須重寫 createState(),返回一個 State,它包含了檢視和互動邏輯
      @override
      State<StatefulWidget> createState() => _FavoriteStatefulWidgetState();
    }
    複製程式碼
  2. 實現一個 State,它提供了真正的 Widget 檢視和互動邏輯。

    class _FavoriteStatefulWidgetState extends State<FavoriteStatefulWidget> {
      bool _isFavorited = true;
      int _favoriteCount = 41;
    
      void _toggleFavorite() {
        // 通過 setState() 更新資料
        // 元件樹就會自動重新整理了
        setState(() {
          if (_isFavorited) {
            _favoriteCount -= 1;
            _isFavorited = false;
          } else {
            _favoriteCount += 1;
            _isFavorited = true;
          }
        });
      }
    
      // 重寫 build() 函式,構建檢視樹
      @override
      Widget build(BuildContext context) => Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Container(
                padding: EdgeInsets.all(0),
                child: IconButton(
                  icon: (_isFavorited ? Icon(Icons.star) : Icon(Icons.star_border)),
                  color: Colors.red[500],
                  onPressed: _toggleFavorite,
                ),
              ),
              SizedBox(
                width: 18,
                child: Container(
                  child: Text('$_favoriteCount'),
                ),
              ),
            ],
          );
    }
    複製程式碼
  3. 使用這個自定義的 StatefulWidget 看看效果。

    main() => runApp(MaterialApp(
          title: 'Flutter Demo',
          home: Scaffold(
            appBar: AppBar(
              title: Text('Flutter Demo'),
            ),
            body: Container(
              color: Colors.white,
              child: Center(
                child: FavoriteStatefulWidget(),
              ),
            ),
          ),
        ));
    複製程式碼

2.2 State 的生命週期

從上面的例子中可以看到,StatefulWidget 會要求提供一個含有檢視樹的 State

既然 State 能夠控制一個檢視的狀態,那它肯定會有一系列的生命週期。

上圖就是 State 的生命週期圖。

  1. StatefulWidget.createState()

    Framework 呼叫會通過呼叫 StatefulWidget.createState() 來建立一個 State。

  2. initState()

    新建立的 State 會和一個 BuildContext 產生關聯,此時認為 State 已經被安裝好了,initState() 函式將會被呼叫。

    通常,我們可以重寫這個函式,進行初始化操作。

  3. didChangeDependencies()

    initState() 呼叫結束後,這個函式會被呼叫。

    事實上,當 State 物件的依賴關係發生變化時,這個函式總會被 Framework 呼叫。

  4. build()

    經過以上步驟,系統認為一個 State 已經準備好了,就會呼叫 build() 來構建檢視。

    我們需要在這個函式中,返回一個 Widget。

  5. deactivate()

    當 State 被暫時從檢視樹中移除時,會呼叫這個函式。

    頁面切換時,也會呼叫它,因為此時 State 在檢視樹中的位置發生了變化,需要先暫時移除後新增。

    ⚠️注意,重寫的時候必須要呼叫 super.deactivate()

  6. dispose()

    當 State 被永久的從檢視樹中移除,Framework 會呼叫該函式。

    在銷燬前觸發,我們可以在這裡進行最終的資源釋放。

    在呼叫這個函式之前,總會先呼叫 deactivate()

    ⚠️注意,重寫的時候必須要呼叫 super.dispose()

  7. didUpdateWidget(covariant T oldWidget)

    當 widget 的配置發生變化時,會呼叫這個函式。

    比如,Hot-reload 的時候就會呼叫這個函式。

    這個函式呼叫後,會呼叫 build()

  8. setState()

    當我需要更新 State 的檢視時,需要手動呼叫這個函式,它會觸發 build()

目錄傳送門:《Flutter快速上手指南》先導篇

如何找到我?

傳送門:CoorChice 的主頁

傳送門:CoorChice 的 Github


相關文章