flutter之InheritedWidget使用

212 阅读2分钟

InheritedWidget

不同于Android的命令式编程(Imperative Programming),每个View都有一个引用ID来进行数据刷新和操作,具体操作具体实现。

Flutter是申明式编程(Declarative Programming),通过申明的方法播放操作广播,不定义具体操作。

Flutter的Widget是Composition(组合)多于Implements(继承)的,也就是层级组件包裹在child字段中。 当Widget树的层级很深时,自然而然涉及到上层组件与深层组件的交互问题。

所以Flutter中使用State Management,也就是数据共享。

在Flutter框架中,最显而易见的数据共享,就是InheritedWidget了。 顾名思义,InheritedWidget就是继承组件。

Widget ⇐ Element ⇒ RenderObject Widget是UI的配置信息,RenderObject才是绘制到屏幕的对象。 Element管控Widget和RenderObject。

updateShouldNotify方法通知什么时候Widget应该更新。

简单使用InheritedWidget来继承文字颜色

dependOnInheritedWidgetOfExactType是在ancestor中查找符合InheritedWidget类型的最近祖先组件。 而每个InheritedElement,都有一个Map<Element,Object>字典属性_dependents,其中key就是每个要监听这个InheritedWidget的底层子widget的对象。 当使用context.dependOnInheritedWidgetOfExactType时,会将当前context放入到ancestor的_dependents,当这个ancestor的属性改变时,就会根据这个字典属性_dependents,更新监听了ancestor的底层子Widget,使得子Widget得以rebuild。没有监听的子组件,就不会重新build。

改变值的InheritedWidget使用

updateShouldNotify: true表示监听此InheritedWidget的Widget在值改变时会重新绘制。false则不会重新绘制。

_getInheritedTextStyle中,如果listen为true,则是从context.dependOnInheritedWidgetOfExactType 中查找InheritedWidget,则会将自己加入_dependents中(如前文所说)。当值改变值,context(即Element)对应的Widget会rebuild,响应数据改变; 如果listen为false,则使用context.findAncestorWidgetOfExactType,只是单纯的一直从ancestor.parent中查找符合条件的InheritedWidget,没有与要查找的InheritedWidget建立监听关系。所以当数据改变时,此context对应的Widget不会rebuild。

State中使用InheritedWidget作为build方法的返回值。

具体使用:

当点击按钮改变颜色时,第一个CustomText因为使用TextStyleWidget.of(context,listen:true)中查找InheritedWidget,所以会响应数据的变化进行Widget的重绘rebuild。对应的第二个CustomText就不会改变,因为没有进行监听。

总结:InheritedWidget提供了层级组件中,上层组件向底层组件提供数据的功能。InheritedWidget是中间桥梁,当底层组件需要监听变化时,会注册自己到最近的InheritedWidget,从而在数据变化时更新自己。