widget state界面刷新原理揭祕

0x00 無狀態組件和狀態組件

widget是fltter界面開發中的基礎控件,如同ios中的uiview這種地位,所謂萬物皆widget。前端

widget有分爲statelessWidget和statefulWidget,這二者是什麼區別呢。一句話就是說statelesswidget用來展現無狀態的視圖,而statefulwidget用來展現可交互的,動態的視圖。ios

到此基本的結論已經出來了,那麼state到底是怎麼實現狀態的更新的?編程

原文發表地址 flutterdev.top小程序

0x01 UI編程範式

iOS和安卓開發採用的是命令式編程範式,而flutter、前端的VUE,小程序開發採用的是聲明式。bash

如 iosapp

UILable * lable  = [UILable new];
label.text = "hello world";
複製代碼

這就是命令式,直接對控件中的屬性進行精準高效的賦值控制。less

然而flutter以下iview

class BgChangeView extends StatefulWidget {
  @override
  _BgChangeViewState createState() => _BgChangeViewState();
  Color color = Colors.red;
}

class _BgChangeViewState extends State<BgChangeView> {
  int count = 10;

  void _incrementCounter() {
    setState(() {
      count = count>255 ? 0 :count + 10;
      widget.color = Color.fromARGB(count, 0x00, 0xff, 0xff);
      print("state refresh count ${count}");

    });
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 100,
      height: 100,
      child: RaisedButton(onPressed: _incrementCounter,
        color: widget.color,
      ),
    );
  }
}

複製代碼

flutterdev.top

將color指定給raisebutton,color在state中更新了,從而更新了raisebuttom的背景顏色ide

0x02 如何實現

state是表示視圖的狀態,當setState觸發當前視圖及其子視圖的銷燬重建,從父視圖到子視圖,從上到下的順序重建。性能

flutterdev.top

猜想內部state的實現

其實state是負責銷燬重建的,在重建的過程當中從新對widget樹一級級生成,並把外部的數據從新對widget進行賦值操做,由於內部機制小部件重建的效率很高,幾乎肉眼看不到它銷燬的過程,可是若是對於root視圖頻繁進行state的操做,會帶來很大的性能開銷,卡頓,cpu,gpu使用率太高等狀況。這也是聲明式編程一個弊端。使用中須要進來避免過多的setState的操做。

PS: 感謝@Vadasik提醒,賦值一說並不許確,查看了一下setate的源碼並非直接賦值的操做,去除一些異常判斷,如正在刷新,是否已經廢棄,是直接將舊的element加入到dirtyelements中,另外再新建新的element ,調用堆棧,setstate->_element.markNeedsBuild();-->owner.scheduleBuildFor(this); 核心代碼以下:

if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
      _scheduledFlushDirtyElements = true;
      onBuildScheduled();
    }
    _dirtyElements.add(element);
    element._inDirtyList = true;
複製代碼

flutter engine內部固然會優化這部分的性能,每次重建以後以前申請的widget或randerobject使用的空間不會一個個的清空釋放,而是採起一直滑動壓縮的方式進行清理。以下圖所示

code4fluttter

  • flutter將內存區域分爲兩部分,活躍空間和不活躍空間
  • 用戶使用app,flutter在活躍空間不斷申請內存空間
  • 直到獲取空間分配滿了
  • 檢查活躍空間中活躍的對象,將活躍的和其所依賴的對象一併標誌
  • 在app空閒時將活躍的對象移動到不活躍區域,此時活躍的對象中間沒有不活躍的區域了
  • 將不活躍的區域和活躍區域交換狀態

參考文章

相關文章
相關標籤/搜索