Flutter 「更新树」涉及到的问题
上篇文章中,我们知道了 Flutter 的视图树中有三种树WidgetElementRenderObject而且,Flutter 建议,Widget 最好是 不可变的(immutable)。问题一但是为什么呢?如果我们的页面数据发生变化,那么视图也需要发生变化,怎么办呢?flutter 界面开发是一种响应式编程,主张 simle is fastflutter 设...
上篇文章中,我们知道了 Flutter 的视图树中有三种树
Widget
Element
RenderObject
而且,Flutter 建议,Widget 最好是 不可变的(immutable)。
问题一
但是为什么呢?如果我们的页面数据发生变化,那么视图也需要发生变化,怎么办呢?
flutter 界面开发是一种响应式编程,主张 simle is fast
flutter 设计的初衷是希望数据变化时,发送通知到对应的可变更节点,这个节点可能是一个 StatefullWidget 子节点,也可能是 rootWidget,由上到下重新 create widget 树进行刷新。
重点是:重新 create widget树
这样的话,思路就比较简单了,就不用关心数据变更会影响到哪些节点了;
而且,将 widget 设置成不可变的,也节省了很多资源。
这个时候,问题二来了
问题二
更新数据,需要更新视图,就得重新创建 Widget ,那么 另外两颗树?也会重新创建吗?
当然不会啦~
如果需要再重新创建一遍,那么这种复杂度和使用 可变的 Widget 就基本没什么区别了。
widget 只是一个 数据结构的配置,是非常轻量的,耗费的资源也是很少的,再加上 flutter 团队对 widget 的创建、销毁都做了优化,所以不用担心整个 widget 树重新创建所带来的性能问题。
但是 RenderObject 就不一样了,RenderObject 涉及到 layout、paint 等复杂操作,是一个真正渲染的 view,整个 view 树重新创建开销就很大了。
既然这样,那么第三个问题也来了:
问题三
只重新创建 Widget ,不重新创建 Element 和 RenderObject,那么怎么实现「视图的更新」呢?
方便起见,大家看图吧~

视图树更新原则
需要注意:
element.child.widget == widget.build() 时,不会触发子树的 update,当触发 update 的时候,如果没有生效,要注意 widget 是否使用就 widget,没有 new widget,导致 update 流程走到改 widget 就停止了
子树的深度变化,会引起子树重建,如果子树是一个复杂度很高的树,可以使用 GlobalKey 作为子树 widget 的key。因为,GlobalKey 具有缓存功能。
问题四
怎样才能出发「视图树更新」即界面更新
-
全局更新:调用 runApp(rootWidget), 这个一般是 flutter 启动时调用,之后不会再调用了
-
局部子树更新,将该子树做 StatefullWidget 的一个子 widget,并创建对应的 State 类实例,通过调用 state.setState() 触发该子树的刷新
总结
这几个问题,对于理解 Flutter 界面更新,应该有一定的帮助吧~~,图是自己对照着「语雀」上面的文章画的,大家有兴趣可以去看看
真心推荐
更多推荐



所有评论(0)