Flutter筆記(二) - 有狀態(tài)的StatefulWidget

1. StatefulWidget

1.1. 認識StatefulWidget

在Flutter開發(fā)中,所有的widget都不能定義狀態(tài);

注意:widget@immutable 修飾的,所以繼承wedget的類內(nèi)部是不能寫變量的,只能用final修飾;
? 創(chuàng)建一個單獨的類,負責維護狀態(tài);

為什么 ?

? 這次因為Flutter在設計的時候就決定了一旦Widget中展示的數(shù)據(jù)發(fā)生變化,就重新構建整個Widget;
? Flutter通過一些機制來限定定義到Widget中的成員變量必須是final的;

為什么Flutter在設計的時候,StatefulWidget的build方法放在State中 ?

? 1. build出來的widget是需要依賴State中的變量(狀態(tài)、數(shù)據(jù));
? 2. 在flutter的運行過程中:
? widget是不斷銷毀和創(chuàng)建的;
? 當我們自己的狀態(tài)發(fā)生改變時,并不希望創(chuàng)建一個新的state;

1.2. 案例展示

WechatIMG38.jpeg
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: YZHomePage()
    );
  }
}

class YZHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text("商品列表")
        ),
        body: YZHomeContent("你好,李煥英")
    );
  }
}

class YZHomeContent extends StatefulWidget {
  final String message;
  YZHomeContent(this.message);
  
  @override
  _YZHomeContentState createState() => _YZHomeContentState();
}

class _YZHomeContentState extends State<YZHomeContent> {

  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          _getButtons(),
          Text("當前計數(shù):$_counter", style: TextStyle(fontSize: 25),),
          Text("傳遞過來的信息:${widget.message}")
        ],
      ),
    );
  }

  Widget _getButtons(){
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        RaisedButton(
            child: Text("+", style: TextStyle(fontSize: 20, color: Colors.white)),
            color: Colors.pink,
            onPressed: () {
              setState(() {
                _counter++;
              });
            }
        ),
        RaisedButton(
            child: Text("-", style: TextStyle(fontSize: 20, color: Colors.white)),
            color: Colors.purple,
            onPressed: () {
              setState(() {
                _counter--;
              });
            }
        )
      ],
    );
  }
}

1.3. StatefulWidget 的生命周期

1.3.1. 生命周期的理解

什么是生命周期呢?

客戶端開發(fā):iOS開發(fā)中我們需要知道UIViewController從創(chuàng)建到銷毀的整個過程,Android開發(fā)中我們需要知道Activity從創(chuàng)建到銷毀的整個過程。以便在不同的生命周期方法中完成不同的操作;

前端開發(fā)中:Vue、React開發(fā)中組件也都有自己的生命周期,在不同的生命周期中我們可以做不同的操作;

Flutter小部件的生命周期:

StatelessWidget可以由父Widget直接傳入值,調(diào)用build方法來構建,整個過程非常簡單;

class YZHomeContent extends StatelessWidget {
  final Sting message;
  YZHomeContent(this.message) {
    print("構造函數(shù)被調(diào)用");
  }
  @override
  Widget build(BuildContext context) {
    print("調(diào)用build方法");
    return Text(message);
  }
}

而StatefulWidget需要通過State來管理其數(shù)據(jù),并且還要監(jiān)控狀態(tài)的改變決定是否重新build整個Widget;

所以,我們主要討論StatefulWidget的生命周期,也就是它從創(chuàng)建到銷毀的整個過程;

1.3.2. StatefulWidget生命周期簡單版

class YZhomeContent extends StatefulWidget {
  @override
  _YZhomeContentState createState() => _YZhomeContentState();
}

class _YZhomeContentState extends State<YZhomeContent> {  
  @override
  Widget build(BuildContext context) {
    return Container(
    );
  }
}

由上面代碼中,我們知道StatefulWidget本身由兩個類組成:StatefulWidgetState;

StatefulWidget 生命周期

首先,執(zhí)行StatefulWidget中相關的方法:

    1. 執(zhí)行StatefulWidget的構造函數(shù)(Constructor)來創(chuàng)建出StatefulWidget;
    1. 執(zhí)行StatefulWidgetcreateState方法,來創(chuàng)建一個維護StatefulWidgetState對象;
      其次,調(diào)用createState創(chuàng)建State對象時,執(zhí)行State類相關方法;
    1. 執(zhí)行State類的構造方法(Constructor)來創(chuàng)建State對象;
    1. 執(zhí)行ininState,我們通常會在這個方法中執(zhí)行一些數(shù)據(jù)初始化的操作,或者也可能會發(fā)送網(wǎng)絡請求;
@protected
  @mustCallSuper
  void initState() {
    assert(_debugLifecycleState == _StateLifecycle.created);
  }

注意:這個方法是重寫父類的方法,必須調(diào)用super,因為父類中會進行一些其他操作;
并且如果你閱讀源碼,你會發(fā)現(xiàn)這里有一個注解(annotation):@mustCallSuper

    1. 執(zhí)行didChangeDependencies方法,這個方法在兩種情況下會調(diào)用

      • 情況一:調(diào)用initState會調(diào)用;
      • 情況二:從其他對象中依賴一些數(shù)據(jù)發(fā)生改變時,比如前面我們提到的InheritedWidget;
    1. Flutter執(zhí)行build方法,來看一下我們當前的Widget需要渲染哪些Widget;
    1. 當前的Widget不再使用時,會調(diào)用dispose進行銷毀;
    1. 手動調(diào)用setState方法,會根據(jù)最新的狀態(tài)(數(shù)據(jù))來重新調(diào)用build方法,構建對應的Widgets;
    1. 執(zhí)行didUpdateWidget方法是在當父Widget觸發(fā)重建(rebuild)時,系統(tǒng)會調(diào)用didUpdateWidget方法;
class YZHomeContent extends StatefulWidget {

  YZHomeContent(){
    print("1.調(diào)用YZHomeContent的construction方法");
  }

  @override
  _YZHomeContentState createState() {
    print("2.調(diào)用YZHomeContent的createState方法");
    return _YZHomeContentState();
  };
}

class _YZHomeContentState extends State<YZHomeContent> {
  _YZHomeContentState() {
    print("3.調(diào)用YZHomeContentState的construction方法");
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    print("4.調(diào)用_YZHomeContentState的initState方法");
  }

  @override
  Widget build(BuildContext context) {
    print("5.調(diào)用_YZHomeContentState的build");
    return Container();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    print("6.調(diào)用_YZHomeContentState的dispose");
    super.dispose();
  }
}

1.3.3. 生命周期的復雜版

  1. mounted是State內(nèi)部設置的一個屬性,事實上我們不了解它也可以,但是如果你想深入了解它,會對State的機制理解更加清晰;
  • 是內(nèi)部設置的,不需要我們手動進行修改;
  1. dirty state的含義是臟的State
  • 它實際是通過一個Element的東西的屬性來標記的;

  • 將它標記為dirty會等待下一次的重繪檢查,強制調(diào)用build方法來構建我們的Widget;

  1. clean state的含義是干凈的State
  • 它表示當前build出來的Widget,下一次重繪檢查時不需要重新build;
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容