0x00 无状态组件和状态组件
widget是fltter界面开发中的基础控件,如同ios中的uiview这种地位,所谓万物皆widget。
widget有分为statelessWidget和statefulWidget,这两者是什么区别呢。一句话就是说statelesswidget用来展示无状态的视图,而statefulwidget用来展示可交互的,动态的视图。
到此基本的结论已经出来了,那么state究竟是怎么实现状态的更新的?
原文发表地址 flutterdev.top
0x01 UI编程范式
iOS和安卓开发采用的是命令式编程范式,而flutter、前端的VUE,小程序开发采用的是声明式。
如 ios
UILable * lable = [UILable new];
label.text = "hello world";
这就是命令式,直接对控件中的属性进行精准高效的赋值控制。
然而flutter如下
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,
),
);
}
}

将color指定给raisebutton,color在state中更新了,从而更新了raisebuttom的背景颜色
0x02 如何实现
state是表示视图的状态,当setState触发当前视图及其子视图的销毁重建,从父视图到子视图,从上到下的顺序重建。

猜测内部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使用的空间不会一个个的清空释放,而是采取一直滑动压缩的方式进行清理。如下图所示

- flutter将内存区域分为两部分,活跃空间和不活跃空间
- 用户使用app,flutter在活跃空间不断申请内存空间
- 直到获取空间分配满了
- 检查活跃空间中活跃的对象,将活跃的和其所依赖的对象一并标志
- 在app空闲时将活跃的对象移动到不活跃区域,此时活跃的对象中间没有不活跃的区域了
- 将不活跃的区域和活跃区域交换状态
参考文章
- flutter核心技术实战 time.geekbang.org/column/arti…
- flutter内存技术 www.helloted.com/flutter/201…