抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

共享原则:

  • 如果状态是组件私有的,则应该由组件自己管理;
  • 如果状态要跨组件共享,则该状态应该由各个组件共同的父元素来管理。

InheritedWidget

InheritedWidget 是 Flutter 中非常重要的一个功能型组件,它提供了一种在 widget 树中从上到下共享数据的方式。

InheritedWidget 的在 widget 树中数据传递方向是从上到下的,这和通知 Notification(将在下一章中介绍)的传递方向正好相反。

下面是“计数器”示例应用程序的 InheritedWidget 版本:

See the Pen InheritedWidget by SukiEva (@sukievaa) on CodePen.

这样,子组件可以调用父组件里的 data 值进行操作。

didChangeDependencies()

一般来说,子 widget 很少会重写此方法,因为在依赖改变后 Flutter 框架也都会调用 build() 方法重新构建组件树。

但是,如果需要在依赖改变后执行一些昂贵的操作,比如网络请求,这时最好的方式就是在此方法中执行,这样可以避免每次 build() 都执行这些昂贵操作。

如果只想在 __TestWidgetState 中引用 ShareDataWidget 数据,但却不希望在 ShareDataWidget 发生变化时调用 __TestWidgetStatedidChangeDependencies() 方法,将 ShareDataWidget.of() 修改一下:

1
2
3
4
static ShareDataWidget of(BuildContext context) {
//return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
return context.getElementForInheritedWidgetOfExactType<ShareDataWidget>().widget;
}

dependOnInheritedWidgetOfExactType()getElementForInheritedWidgetOfExactType() 多调了 dependOnInheritedElement 方法,dependOnInheritedElement 源码如下:

1
2
3
4
5
6
7
8
@override
InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object aspect }) {
assert(ancestor != null);
_dependencies ??= HashSet<InheritedElement>();
_dependencies.add(ancestor);
ancestor.updateDependencies(this, aspect);
return ancestor.widget;
}

调用 dependOnInheritedWidgetOfExactType()getElementForInheritedWidgetOfExactType() 的区别:
前者会注册依赖关系,而后者不会

Provider

InheritedWidget 组件的上层封装,使其更易用,更易复用。

使用 provider 而非手动书写 InheritedWidget,有以下的优势:

  • 简化的资源分配与处置
  • 懒加载
  • 创建新类时减少大量的模板代码
  • 支持 DevTools
  • 更通用的调用 InheritedWidget 的方式(参考 Provider.of/Consumer/Selector
  • 提升类的可扩展性,整体的监听架构时间复杂度以指数级增长(如 ChangeNotifier, 其复杂度为 O(N))

更多 provider 相关内容,请参考 文档

评论



Modify from Volantis theme Powered by Hexo