10 | Widget中的State到底是什么?
10 | Widget中的State到底是什么?
讲述:陈航
时长12:07大小11.10M
UI 编程范式
StatelessWidget
StatefulWidget
StatefulWidget 不是万金油,要慎用
总结
思考题
赞 7
提建议
精选留言(43)
- 加温后的啤酒2019-07-22老师,有一个疑问没有理解。你文中提到如果根布局是StatefulWidget,如果调用setState,就会触发子widet的销毁和重建,影响性能。但是在真实业务场景中,我把跟控制器写成StatefulWidget,但我默认他是不可变的,所以我肯定不会主动去调用setState方法啊,那如果我不主动调用setState的话,那不就不会有应能影响了吗。这没法说明StatelessWidget的存在是必要的的??老师能解释一下吗?
作者回复: 实际上你即使不去主动setState,对于Stateful在特定的时机也会rebuild的。具体可以参看下一篇文章
共 2 条评论36 - JakePrim2019-07-20就喜欢这种讲解加举例的方式,非常清晰19
- Mr.J2019-07-21构建界面时,抛开业务,光看界面,把界面按层次拆分,需要动态更新的地方,用Stateful,然后将其统一放在Stateless中,做到例如在一个小区域中,根布局也是Stateless,其中有一个控件为stateful,刷新时只刷新这个小部分,这样吗老师
作者回复: 是的
10 - JW2019-09-27Element是Widget层的一个抽象用来处理真正需要重建的的Widget,它是如何来决定谁要重建谁不要重建的逻辑的?
作者回复: 1.Widget通知Element重建的触发时机,可以参考第11篇生命周期的分享。 2.一旦Widget触发重建,Element会根据重建前后Widget树的渲染类型及属性变化情况,决定后续的复用、新建过程:比如Widget树中仅仅是调整了一个渲染样式,Flutter会通知Element直接复用现有节点,同步属性至RenderObject,触发绘制即可;如果Widget树中涉及到Widget类型的替换或变更,Flutter则会将老的Element及RenderObject摘除,让新的Widget重新走一遍创建Element和RenderObject的流程,挂载到Element树和RenderObject树上。
8 - (☆_☆)2019-07-20简单来说StatelessWidget就是为了提升性能而被设计出来,而完全使用StatefulWidget可能对性能有影响,所以在使用前一定要评估一下用哪个比较合适,这样理解对吗?
作者回复: 是的
7 - Lgh2021-09-27有个比较尴尬的问题,我想问问老师,为什么text是statelesswidget?Text的文案变化不应该属于可变的吗?共 2 条评论3
- 、轻2019-08-14这两个widget与react中的容器和组件很类似
作者回复: 是类似的概念
3 - 格格2019-08-05现在Image里已经找不到_handleImageChanged方法了,好像被_handleImageFrame取代了
作者回复: 确实,1.5还有,1.7已经把这个方法替换掉了。
3 - 承香墨影2019-07-30老师,你好,有个疑问希望解答。 既然 StatefulWidget 需要区分场景来使用,并且 Widget 的销毁和重建应该是 Flutter 的常态。那么在使用中,应该将 StatefulWidget 尽量的拆小,让其影响范围,尽可能的小。 这是不是就对应到 “04 | Flutter 区别于其他方案的关键技术是什么” 中讲到的 布局边界 和 重绘边界 概念。其实在实际代码中,是依赖 StatelessWidget 进行设定边界,从而隔离布局和重绘的?展开
作者回复: 不是的哈。 1.重绘边界是解决同层Widget(有兄弟、有父子)之间渲染依赖出现的概念:即只要他们享用了同一个layer,则无论哪一个需要重绘,整个layer都会受到影响。 2.StatefulWidget则影响的是其子节点,一般情况下只影响重建,Element会在底层做diff,确保没有修改的不会重绘
3 - 矮个子先生😝2019-08-13``` const Image({ Key key, @required this.image, // 其他参数 }) : assert(image != null), super(key: key); ``` 老师可以介绍下这个构造方法吗, 第一个Key key, : assert(image != null),super(key: key); 这三部分展开
作者回复: 1.key用在Element复用过程中,控制控件如何取代树中的另一个控件。比如你在父Widget用新的image重建了Image,底层Element还是能复用的。 2.assert是断言,只在debug中生效。 3.super我们在Dart里面讲过,是调用父类的构造方法
2 - G2019-07-22我查了下资料,好像是说虽然widget是不可变的,但是state是可变的,也就是说state实例会被复用,并且在setstate重新生成widget树时会检查节点是否有变化,没有变化就停止遍历。另外我认为stateful的实例相比stateless更轻,毕竟没有build方法。 Ps: 在递归下降生成子树的时候,我有个疑问,flutter如何判断子树一样呢?算法是如何的?
作者回复: 靠类型和key
共 2 条评论2 - 曾家二女婿2020-01-10【思考题】 void main() => runApp(MyApp()); class MyApp extends StatefulWidget { MyApp({Key key}) : super(key: key); @override _MyApp createState() => _MyApp(); } class _MyApp extends State<MyApp> { bool check = true; void _updateIndeView() { setState(() { check = !check; }); } @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', // 应用的名字 theme: ThemeData( // 蓝色主题 primarySwatch: Colors.red, ), // 首页路由 home: Scaffold( // 点击 切换 主页 body: Container( child: InkWell( onTap: _updateIndeView, child: check ? MyHomePage(title: 'Flutter Demo Home Page') : _MyHomePageDemo(), ) // check ? MyHomePage(title: 'Flutter Demo Home Page') : _MyHomePageDemo(), ), ), ); } }展开1
- Captain2019-11-14有个问题请教“虽然 Flutter 内部通过 Element 层可以最大程度地降低对真实渲染视图的修改,提高渲染效率,而不是销毁整个 RenderObject 树重建。但,大量 Widget 对象的销毁重建是无法避免的”这里 如果根节点用了Stateful,根节点setState,来改变其中变化的子节点状态(子节点状态中没有耗时操作),那Element会帮助diff出变化的子节点,避免重新构建,这样也不影响性能呀?
作者回复: “但,大量的Widget对象的销毁重建是无法避免的”
1 - 严旭珺2019-08-08感觉项目的一个优化方向就是尽量用statelesswidget
作者回复: 是的
1 - 吴小安2019-08-07请问这种声明式编程在ios和安卓业界有没有简单的框架能用的? 感觉现在ios使用的面向数据开发也都是命令式编程,界面绑定某个值,kvo变化了在回调里做刷新ui的操作,怎样能向这种声明式转移
作者回复: Litho和Texture(AsyncDisplayKit)算一个,不过框架整体比较重,有一定学习成本
共 2 条评论1 - 徐西文2019-07-23Dart为什么不设计一种可以自动选择状态的widget
作者回复: 因为simple is best,另外Element已经拦截不必要的绘制了
1 - Bula2019-07-22StatefulWidget感觉很难减少使用频率啊 现在的设计标题栏的标题都是要跟着状态改变动态更改 😓
作者回复: 拆小就行了
1 - Eren2019-07-20学到现在,真的是受益匪浅,之前的一些疑惑都从中得到了答案,有种恍然大悟的感觉,希望老师能在未来的学习中,分享一下 Flutter 的从业情况和面试题,感谢之至。
作者回复: 会讲一部分
1 - Egos2019-07-20思考题里面是将MyApp 替换成StatefulWidget,然后需要在点击FloatingActionButton 的时候更新MyApp 的State 么?这样需要将MyApp 的State 一直传递到_MyHomePageState?
作者回复: 是的
1 - 张简2019-07-20清楚明白1