跟🤡杰哥一起学Flutter (十三、从Widget源码 ✈ InheritedWidget)

💡 原文中文,约17300字,阅读约需42分钟。
📝

内容提要

本文介绍了Flutter中Widget的基本概念和使用方法,包括Widget的结构、布局和样式,以及StatefulWidget和StatelessWidget的区别。还介绍了InheritedWidget的使用和Widget的生命周期。

🔎

延伸解读

Widget 不可变性的设计意图

文章强调 Widget 一旦创建就不可修改,每次状态变化都会生成新的 Widget 树。这种不可变性并非限制,而是性能优化的关键:Flutter 可以快速比较新旧 Widget 的 runtimeType 和 key,决定是否复用 Element,从而避免重建整个 UI 树。理解这一点有助于在开发中合理使用 const 构造函数和 Key,减少不必要的重建。

BuildContext 与 Element 的实质关系

源码注释指出 BuildContext 实际上就是 Element 对象,接口设计是为了防止直接操作 Element。这意味着通过 context 可以访问 Element 树的信息,如查找祖先 Widget、注册依赖等。但需注意,不同 API 对调用时机有要求,例如在 build 中直接使用 Scaffold.of(context) 可能失败,因为 Scaffold 尚未创建。此时应使用 Builder 获取子树的 context,或改用 ScaffoldMessenger。

InheritedWidget 的依赖注册机制

InheritedWidget 通过 dependOnInheritedWidgetOfExactType 注册依赖关系,当共享数据变化时,会通知依赖的 Element 调用 didChangeDependencies 并重建。如果只想读取数据而不希望因数据变化触发重建,可以使用 getElementForInheritedWidgetOfExactType,因为它不会注册依赖。这一区别在需要优化性能或避免不必要的回调时非常实用。

setState 后的异步更新流程

setState 最终调用 markNeedsBuild,将 Element 标记为 dirty 并加入重建队列,但 UI 不会立即更新,而是等到下一帧由 BuildOwner 统一处理。这解释了为什么在 setState 后不能立即获取更新后的 UI 状态。同时,在 build 阶段调用 setState 会抛出异常,因为此时正在构建,不允许标记重建。理解这一流程有助于避免常见的状态更新错误。

❓

Q&A

Flutter中的Widget是什么?

Widget是Flutter中所有UI元素的基础,包含结构、布局和样式。

StatefulWidget和StatelessWidget有什么区别?

StatelessWidget用于展示不需要状态变化的UI,而StatefulWidget用于需要保存状态的UI。

InheritedWidget的作用是什么?

InheritedWidget用于高效地共享数据,避免手动传递数据。

Flutter的Widget重建流程是怎样的?

Widget重建通过markNeedsBuild()标记Element为dirty,触发UI更新。

什么是BuildContext,它有什么用?

BuildContext用于访问Widget树中的信息,提供与Element交互的方式。

Flutter中如何管理StatefulWidget的状态?

StatefulWidget的状态由State类管理,支持状态的持久化和更新。

🏷️

标签

➡️

继续阅读