
往期相关内容
- Flutter State Management状态管理全面分析:https://www.jianshu.com/p/9334b8f68004
- Flutter Provider 迄今为止最深、最全、最新的源码分析:https://juejin.im/post/6844904176074358791
- Flutter之万物皆Widget:https://juejin.im/post/6873323337016311816
前言
在上期,我们手写了一个Widget的实现,并接触到了Element,经过一系列的分析,我们对Widget和Element的认识更进一步,那么这期我们就来深入理解下State,相信大家在开发过程中,总会用到StatefulWidget,那么官方为什么设计一个含有State的Widget?State生命周期是怎么来的?为什么State可以更新UI?带着一些疑问,我们不直接分析源码,而是手写一个带有State的Widget怎么样?我们来做一个带State的Widget,让它有生命周期和更新UI的能力。
本次主要内容
- 宏观看state是什么,微观看State
- State类继承关系图
- 手写一个带State的Widget
宏观看state是什么,微观看State

从宏观来看,flutter的UI是声明式的,那为什么是声明式?这就要从Win32到Web再到Android和Ios说起,他们都是命令式的编程风格,如下:
//android
TextView tv = TextView()
tv.setText("text")
当UI发生变化的时候,你必须调用setText来实现,但flutter恰相反,它为了减轻开发人员的负担,让开发人员只关心当前应用的状态,并交给框架自动将状态通过函数渲染在UI上,那么这样做有什么好处呢?
- 开发人员只关心状态的变化,从架构上做到了UI和数据的分离
- 更深入的讲,其实flutter 真实的UI对象是RenderObjects,Widget是不变的,每次刷新UI都会构建新的子Widget树,并通过Element过滤,最终RenderObject只是很小的改动,提高了渲染的效率。
那么有什么缺点吗?
- 不合理的状态管理,导致整个页面的频繁build
- 在Widget树中加入了状态的计算,会导致状态管理的混乱,不统一
最理想的就是如上图的公式:UI= f(state) 举个例子:
class TestState extends StatefulWidget {
@override
_TestState createState() => _TestState();
}
class _TestState extends State<TestState> {
FunState _funState = FunState();
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
Text(_funState.state + "state"), /// 不推荐
Text(_funState.getState()) /// 推荐写法,f(state)
],
),
);
}
}
class FunState {
String state = "state";
getState() {
return state + "Test";
}
}
看到了吧,我们不推荐你这样哦
Text(_funState.state + "state"), /// 不推荐
这就是我要说的宏观state,我们简单做个定义:state其实就是反应出当前UI的状态。那么微观呢?其实就是StatefulWidget的State,都知道每个StatefulWidget会对应一个State,上期我们也学习了Widget,了解到Widget实际上是通过Element来展示UI的,那么State到底是什么角色,有什么作用呢?或者说,为什么google要这么设计呢?让我们来慢慢揭晓答案,并最终总结一下。
State类继承关系图

像我常用的Form,FormField,Overlay,Scaffold Widget,它们都会对应一个自己的State,当然也有更深一层的继承关系如AnimatedWidgetBaseState,但它的子类都是私有的。以及其他的State,通过类的继承关系,大致了解到,State类不需要特别深入的继承关系,比Widget和Element都稍微简单一些,flutter在设计之初,就一致贯穿一个设计思想就是组合大于继承,所以这也是整个UI框架的特点,也是类图都很简单的主要原因。
手写一个带State的Widget
我们还是上期的套路,继承最底层的Widget来实现,这次加一个State,来伪装成StatefulWidget,来吧。