当前位置: 首页 > news >正文

西安网站制作一般多少钱百度搜索推广官网

西安网站制作一般多少钱,百度搜索推广官网,如何设置的iis后台服务网站地址,学生做义工网站InheritedWidget的核心是保存值和保存使用这个值的widget,通过对比值的变化,来决定是否要通知那些使用了这个值的widget更新自身。 1 updateShouldNotify和notifyClients InheritedWidget通过updateShouldNotify函数控制依赖其的子组件是否在Inherited…

 InheritedWidget的核心是保存值和保存使用这个值的widget,通过对比值的变化,来决定是否要通知那些使用了这个值的widget更新自身。

1 updateShouldNotify和notifyClients

InheritedWidget通过updateShouldNotify函数控制依赖其的子组件是否在InheritedWidget变化时会被重建:如果updateShouldNotify返回true,InheritedWidget变化时子组件的build会被调用,反之则不会。

InheritedElement中的updated方法:

@override
void updated(InheritedWidget oldWidget) {if (widget.updateShouldNotify(oldWidget))super.updated(oldWidget);
}

InheritedElement继承于ProxyElement,而ProxyElement的updated实现为:

@protectedvoid updated(covariant ProxyWidget oldWidget) {notifyClients(oldWidget);}

而InheritedElement的notifyClients实现是遍历_dependents中依赖自己的widget,然后调用它的didChangeDependencies进行变化通知:

  @overridevoid notifyClients(InheritedWidget oldWidget) {assert(_debugCheckOwnerBuildTargetExists('notifyClients'));for (final Element dependent in _dependents.keys) {assert(() {// check that it really is our descendantElement? ancestor = dependent._parent;while (ancestor != this && ancestor != null) {ancestor = ancestor._parent;}return ancestor == this;}());// check that it really depends on usassert(dependent._dependencies!.contains(this));notifyDependent(oldWidget, dependent);}}@protectedvoid notifyDependent(covariant InheritedWidget oldWidget, Element dependent) {dependent.didChangeDependencies();}
Element的didChangeDependencies源码如下:void didChangeDependencies() {assert(_active); // otherwise markNeedsBuild is a no-opassert(_debugCheckOwnerBuildTargetExists('didChangeDependencies'));markNeedsBuild();
}

可以看到,InheritedWidget变化时,如果updateShouldNotify是true,会通过notifyClients调用子组件的didChangeDependencies函数,从而调用markNeedsBuild,将本Element加入_dirtyElements列表中。大家都知道,_dirtyElements中保存的是需要重建的Element,会在下一帧时被rebuild,因此在下一帧子组件会被重建(rebuild)。

2 InheritedWidget的传递

InheritedWidget能用于让用户快速从子组件获取,这是怎么实现的呢?

其实Flutter Framework也是将InheritedWidget一层层传递下来的,只不过由于Framework层自行处理了,因此这个过程对于我们是透明的。我们现在来梳理下InheritedWidget传递的过程。

Element中,有一个map:_inheritedWidgets。保存了所有上级节点中的InheritedElement。其源码如下:

Map<Type, InheritedElement> _inheritedWidgets;

其中,key中Type是InheritedWidget的子类,value是InheritedElement。为什么这里value保存的是InheritedElement而不是InheritedWidget呢?由以前的文章可以知道Element中保存着对应Widget的引用,因此可以通过InheritedElement获取对应的InheritedWidget。而且Widget在上级Widget重建时会被重建,因此保存InheritedElement更合适。

在普通的Element中,_inheritedWidgets会直接复制其父组件中_inheritedWidgets的值,其源码如下:

void _updateInheritance() {assert(_active);_inheritedWidgets = _parent?._inheritedWidgets;
}

而在InheritedElement中,_inheritedWidgets会首先复制其父组件中_inheritedWidgets的值,然后将自己添加进列表,其源码如下:

@override
void _updateInheritance() {assert(_active);final Map<Type, InheritedElement> incomingWidgets = _parent?._inheritedWidgets;if (incomingWidgets != null)_inheritedWidgets = HashMap<Type, InheritedElement>.from(incomingWidgets);else_inheritedWidgets = HashMap<Type, InheritedElement>();_inheritedWidgets[widget.runtimeType] = this;
}

由此可以看出,InheritedElement就是这样一层层传递下来的。_inheritedWidgets赋值流程如下:

由该流程图可以看出,_inheritedWidgets在Element被加入Element Tree时就已经被赋值,因此其在子组件的build函数中是可以访问得到的。

3 InheritedWidget的获取及注册依赖

我们已经知道了InheritedElement会传递到下级组件中,那怎么获取它呢?Flutter提供了专门获取某个InheritedWidget类型的函数dependOnInheritedWidgetOfExactType.其源码如下:

@override
T dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object aspect}) {assert(_debugCheckStateIsActiveForAncestorLookup());final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[T];if (ancestor != null) {assert(ancestor is InheritedElement);return dependOnInheritedElement(ancestor, aspect: aspect) as T;}_hadUnsatisfiedDependencies = true;return null;
}

由第三行可以看出,此函数会从_inheritedWidgets中寻找对应的InheritedElement,并返回其InheritedWidget。

除了dependOnInheritedWidgetOfExactType,Flutter还提供了另一个专门获取某个InheritedWidget类型的函数:getElementForInheritedWidgetOfExactType。其源码如下:

@override
InheritedElement getElementForInheritedWidgetOfExactType<T extends InheritedWidget>() {assert(_debugCheckStateIsActiveForAncestorLookup());final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[T];return ancestor;
}

对比其与dependOnInheritedWidgetOfExactType源码,可以看到dependOnInheritedWidgetOfExactType多了dependOnInheritedElement函数的调用,该函数用于创建InheritedWidget和调用dependOnInheritedWidgetOfExactType的组件的依赖关系。其有两个步骤:

  • 将依赖的InheritedElement加入本Element的_dependencies列表,该列表中保存了本Element所有依赖的InheritedElement.
  • 将本Element加入依赖的InheritedElement的_dependents map,该列表中保存了所有依赖该InheritedElement的Element。

如果使用的是dependOnInheritedWidgetOfExactType,则当被依赖的InheritedWidget被更新时,依赖的子组件会被rebuild;而使用的是getElementForInheritedWidgetOfExactType时,由于不会建立相应的依赖关系,InheritedWidget被更新时,依赖的子组件不会被rebuild。

4 主动调用dependOnInheritedWidgetOfExactType

 子组件需要通过调用dependOnInheritedWidgetOfExactType来获取InheritedWidget,并且将自己加入该InheritedWidget的依赖中。方便起见,一般会在InheritedWidget子类中实现of方法:

class ShareDataWidget extends InheritedWidget {ShareDataWidget({@required this.data,Widget child}) :super(child: child);final int data; //需要在子树中共享的数据,保存点击次数//定义一个便捷方法,方便子树中的widget获取共享数据static ShareDataWidget of(BuildContext context) {return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();}//该回调决定当data发生变化时,是否通知子树中依赖data的Widget@overridebool updateShouldNotify(ShareDataWidget old) {//如果返回true,则子树中依赖(build函数中有调用)本widget//的子widget的`state.didChangeDependencies`会被调用return old.data != data;}
}class _TestWidget extends StatefulWidget {@override__TestWidgetState createState() => new __TestWidgetState();
}class __TestWidgetState extends State<_TestWidget> {@overrideWidget build(BuildContext context) {print("__TestWidgetState build");//使用InheritedWidget中的共享数据return Text(ShareDataWidget.of(context).data.toString());// return Text("tex");}@overridevoid didChangeDependencies() {super.didChangeDependencies();//父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用。//如果build中没有依赖InheritedWidget,则此回调不会被调用。print("Dependencies change");}
}

参考:

Flutter框架分析 -InheritedWidget - 知乎

http://www.hkea.cn/news/321252/

相关文章:

  • 网站开发开题报告ppt竞价运营是做什么的
  • 网站代理怎么做的网站推广策划思路
  • 长沙网站seo公司百度权重5的网站能卖多少钱
  • 常德网站开发百度推广登录首页网址
  • 网站建设软件设计推广官网
  • 网站运营阶段站长之家app
  • discuz网站标题百度广告推广价格
  • 广州学校论坛网站建设疫情排行榜最新消息
  • 古董手表网站网络营销的主要方式和技巧
  • 做公司网站要那些资料百度电脑版下载官方
  • 定州网站建设公司企业网站源码
  • 0基础1小时网站建设教程如何给自己的公司建网站
  • 成都网站建设s1emens电商平台怎么加入
  • 六合哪家做网站建设域名注册查询软件
  • 网站建设的方案费用2023年新冠疫情最新消息
  • 九星市场做网站快速将网站seo
  • 长春做网站推广的公司提升神马关键词排名报价
  • 金融网站cms百度网盘客服电话人工服务
  • 美观网站建设物美价廉seo网站优化专员
  • 网站设计应该怎么做推广软文代写
  • 网站建设工作室发展百度收录教程
  • 没有网站 可以做百度口碑吗成都网站制作
  • 医院系统网站建设百度宁波营销中心
  • 网站劫持代码杭州互联网公司排名榜
  • 做网站找哪个部门吸引人的推广标题
  • 网站制作软件名字线做竞价推广代运营公司
  • avada如何做中英文网站沈阳百度推广排名优化
  • 做网站品长沙网络营销公司排名
  • b2b商贸网站环球网最新消息疫情
  • wordpress next主题什么是seo教程