内容简介:可以说是目前 全网 最完整的返回给定类型的最近父
demo
地址: github.com/LZQL/flutte…
可以说是目前 全网 最完整的 demo
演示了
2. ancestorWidgetOfExactType
返回给定类型的最近父 widget
,该 widget
的类型必须是具体 widget
的子类。
一般来说, inheritFromWidgetOfExactType
更有用,因为继承的 widget
将在更改时触发消费者重新构建。 ancestorWidgetOfExactType
适用于交互事件处理程序(例如手势回调)或执行一次性任务,例如 断言
您拥有或不具有作为特定类型的父 widget
。 widget
的构建方法的返回值不应该依赖于该方法返回的值,因为如果该方法的返回值发生更改,构建上下文将 不会重新生成
。这可能会导致生成方法中使用的数据发生更改,但是没有重新生成 widget
。
总结一下上面的意思:
-
ancestorWidgetOfExactType
一般用于 断言,是否有特定类型的父widget
-
ancestorWidgetOfExactType
可以用来获取父widget
的一些信息 - 如果想要根据方法的返回值来判断是否重新构建,
ancestorWidgetOfExactType
并不适用
下面会分别给出 上面的 3
点总结来给出 demo
场景
1. 断言
这边就不给出自己的 demo
,直接看源码,源码的应用场景说明一切,这边也是官方翻译的最好证明
Hero
的源码,做了断言,断言就写到这里
2. 获取父 widget
的一些信息
1. 代码结构
2. 运行效果
WidgeC
是一个 加号按钮, 点击了 WidgeC
,获取 HomepageState
调用 incrementCounter
方法, , widgetA
, widgetB
, widgetC
会重新 build
,看下图
3. 具体代码
代码位置 ancestor01.dart
/// ancestorWidgetOfExactType 获取父widget的一些信息 class MyAncestorTree01 extends StatefulWidget { @override _MyAncestorTree01State createState() => _MyAncestorTree01State(); } class _MyAncestorTree01State extends State<MyAncestorTree01> { @override Widget build(BuildContext context) { return TopPage01(); } } class TopPage01 extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar( title: Text('Demo'), ), body: HomePage(), ), ); } } class HomePage extends StatefulWidget { final HomePageState state = HomePageState(); @override HomePageState createState() { return state; } } class HomePageState extends State<HomePage> { int counter = 0; void incrementCounter() { setState(() { counter++; }); } @override Widget build(BuildContext context) { return Scaffold( body: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ WidgetA(), WidgetB(), WidgetC(), ], ), ); } } class WidgetA extends StatelessWidget { @override Widget build(BuildContext context) { /// 获取 HomePageState 来获取 counter final HomePage widget = context.ancestorWidgetOfExactType(HomePage); final HomePageState state = widget?.state; return Center( child: Text( '${state == null ? 0 : state.counter}', style: Theme.of(context).textTheme.display1, ), ); } } class WidgetB extends StatelessWidget { @override Widget build(BuildContext context) { return Text('Widget B Text'); } } class WidgetC extends StatelessWidget { @override Widget build(BuildContext context) { /// 获取 HomePageState 来 调用 加法操作 final HomePage widget = context.ancestorWidgetOfExactType(HomePage); final HomePageState state = widget?.state; return RaisedButton( onPressed: () { state?.incrementCounter(); }, child: Icon(Icons.add), ); } } 复制代码
3. 子widget无法检测到父widget的更改
此 demo
用来演示 子widget无法检测到父widget的更改
的具体情况 为后面的内容做铺垫 我将 ancestorWidgetOfExactType
封装了一个 of 方法放到了 TopPage02
里面, 与 2. 获取父widget 的一些信息
的使用场景不同。
1. 代码结构
2. 运行效果
注意看下图,当我点击了 1 - AncestorWidgetOfExactType02 演示
按钮,进入 demo
页面,从右侧可以看出,因为是第一次进去,所以全部 widget
都进行了 build
操作,但是当我 点击 了 Add item
按钮, TopPage02
会 rebuild
但是 WidgetA
, WidgetB
, WidgetC
,并不会进行 rebuild
3. 具体代码
代码位置 ancestor02.dart
/// ancestorWidgetOfExactType /// 子widget无法检测到父widget的更改 /// (父widget rebuild 子widget no rebuild) class MyAncestorTree02 extends StatelessWidget { @override Widget build(BuildContext context) { return new TopPage02( child: new Scaffold( appBar: new AppBar( title: new Text('Title'), ), body: new Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ new WidgetA(), new WidgetB(), new WidgetC(), ], ), ), ); } } class Item { String reference; Item(this.reference); } class TopPage02 extends StatefulWidget { TopPage02({ Key key, this.child, }) : super(key: key); final Widget child; final TopPage02State state = new TopPage02State(); @override TopPage02State createState() { return state; } static TopPage02State of(BuildContext context) { /// 通过从 TopPage02 的 context 得到树结构来返回第一个 TopPage02State return (context.ancestorWidgetOfExactType(TopPage02) as TopPage02) .state; } } class TopPage02State extends State<TopPage02> { List<Item> _items = <Item>[]; int get itemsCount => _items.length; void addItem(String reference) { setState(() { _items.add(new Item(reference)); }); } @override Widget build(BuildContext context) { return widget.child; } } class WidgetA extends StatefulWidget { @override _WidgetAState createState() => _WidgetAState(); } class _WidgetAState extends State<WidgetA> { @override Widget build(BuildContext context) { final TopPage02State state = TopPage02.of(context); return new Center( child: new RaisedButton( child: new Text('WidgetA :Add Item'), onPressed: () { /// 这边调用 addItem 方法,但是WidgetA,WidgetB,WidgetC /// 并不会 build /// 这就说明了:widget的构建方法的返回值不应该依赖于该方法返回的值, /// 因为如果该方法的返回值发生更改,构建上下文将不会重新生成。 /// 这可能会导致生成方法中使用的数据发生更改,但是没有重新生成widget state.addItem('new item'); }, ), ); } } class WidgetB extends StatelessWidget { @override Widget build(BuildContext context) { final TopPage02State state = TopPage02.of(context); return new Text('widgetB itemCount:${state.itemsCount}'); } } class WidgetC extends StatelessWidget { @override Widget build(BuildContext context) { return new Text('I am Widget C'); } } 复制代码
3. InheritedWidget
1. 什么是 InheritedWidget
特性:
-
InheritedWidget
是一个可以在树中高效地向下传递数据
的组件:我们可以在以InheritedWidget
为节点的树下任一Widget
中调用BuildContext.inheritFromWidgetOfExactType
来获取离其最近的InheritedWidget
实例 - 当以上面这种方式(调用
inheritFromWidgetOfExactType
方法时)被引用后,每当InheritedWidget
自身的状态改变时,会导致“consumer”
(调用inheritFromWidgetOfExactType
方法的这个Child
) 重新build
第一点:在 Flutter
中,正是通过 InheritedWidget
来共享应用主题( Theme
)和 Locale
(当前语言环境)信息的 第二点:解决了 上面提到 ancestorWidgetOfExactType
的第三点不能通过返回值来进行重新 build
的情况
InheritedWidget
的在 Widget
树中数据传递方向是从上到下的,这和 Notification
的传递方向正好相反。(后面系列文章介绍 Notification
)
2. didChangeDependencies
StatefulWidget
的 State
对象有一个回调 didChangeDependencies
,它会在“依赖”发生变化时被 Flutter Framework
调用。而这个“依赖”指的就是是否使用了父 widget
中 InheritedWidget
的数据,如果使用了,则代表有依赖,如果没有使用则代表没有依赖。这种机制可以使子组件在所依赖的主题、 locale
等发生变化时有机会来做一些事情。
4. 通过 2 - InheritedWidget演示01
,发现问题
这个例子 是参照 book.flutterchina.club/chapter7/in… 写的一样,相信很多人都看过
1. 代码结构
2. 效果图
当我点击了 click me
按钮 加1, widgetA
, widgeB
, RaisedButton
会重新 build
3. 代码
代码位置: inheritedwidget01.dart
/// InheritedWidget01 , 会导致 `widgetA`,` widgeB`,`RaisedButton `会重新`build` class InheritedWidgetTest01 extends StatefulWidget { @override State<StatefulWidget> createState() { return InheritedWidgetTest01State(); } } class InheritedWidgetTest01State extends State<InheritedWidgetTest01> { int tmpData = 0; @override Widget build(BuildContext context) { print('InheritedWidgetTest01 build'); return Scaffold( body: Center( child: ShareInherited( data: tmpData, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ WidgetA(), WidgetB(), RaisedButton( child: Text("Click me"), onPressed: () { setState(() { print('onPressed'); tmpData += 1; }); }, ), ], ), ), ), ); } } class ShareInherited extends InheritedWidget { final int data; //需要在子树中共享的数据,保存点击次数 ShareInherited({@required this.data, @required Widget child}) : super(child: child) { print('ShareInherited construct'); } /// 允许所有子 widget 通过包含的 context 获得最近的 ShareInherited 实例 /// 定义一个便捷方法,方便子树中的widget获取共享数据 /// 在内部,除了简单地返回 ShareInherited 实例外,它还订阅消费者 widget 以便用于通知更改 static ShareInherited of(BuildContext context) { return context.inheritFromWidgetOfExactType(ShareInherited); } /// 用来告诉 InheritedWidget 如果对数据进行了修改, /// 是否必须将通知传递给所有子 widget(已注册/已订阅) @override bool updateShouldNotify(ShareInherited oldWidget) { // 如果返回true,则子树中依赖(build函数中有调用)本widget // 的子widget的`state.didChangeDependencies`会被调用 bool result = oldWidget.data != this.data; print('ShareInherited updateShouldNotify result = $result'); return result; } } class WidgetA extends StatefulWidget { @override _WidgetAState createState() => _WidgetAState(); } class _WidgetAState extends State<WidgetA> { @override Widget build(BuildContext context) { print('WidgetA build'); int data = ShareInherited.of(context).data; return Text('WidgetA data = $data'); } @override void didChangeDependencies() { print('WidgetA didChangeDependencies'); super.didChangeDependencies(); } } class WidgetB extends StatefulWidget { @override _WidgetBState createState() => _WidgetBState(); } class _WidgetBState extends State<WidgetB> { @override Widget build(BuildContext context) { print('WidgetB build'); return Text('WidgetB'); } @override void didChangeDependencies() { print('WidgetB didChangeDependencies'); super.didChangeDependencies(); } } 复制代码
4. 发现的现象
WidgetA
调用了 inheritFromWidgetOfExactType
方法,获得了存放在 ShareInherited
对象里的 data
数据并显示在 WidgetA
内容上,同时使得 WidgetA
和 ShareInherited
产生关联;
当点击 RaisedButton
触发 InheritedWidgetTest01
状态更新时, InheritedWidgetTest01State
的 build
方法回调,重新构建 ShareInherited
对象传入新值,由于 data
发生变化, ShareInherited
的方法 updateShouldNotify
中返回了 true
,最终使得与 ShareInherited
关联的 WidgetA
触发 reBuild
。
当我们运行并点击 RaisedButton
后,页面表现得确实如上述所示, WidgetA
的内容由 WidgetA data = 0
变为了 WidgetA data = 1
,似乎 InheritedWidget
正确的使用方式正是如此,但是 log
里输出的却是如下:
I/flutter (11303): onPressed I/flutter (11303): InheritedWidgetTest01 build I/flutter (11303): ShareInherited construct I/flutter (11303): ShareInherited updateShouldNotify result = true I/flutter (11303): WidgetA didChangeDependencies I/flutter (11303): WidgetA build I/flutter (11303): WidgetB build 复制代码
可以看到,结合前面的代码逻辑分析,理论上只有 WidgetA
才会 reBuild
,而现在却产生了 I/flutter (11303): WidgetB build
这条记录。这是为什么呢?
5. 原因分析
其实可以从前面提到的 特性2
找到答案。其中说到: InheriteWidget
状态发生变化时会 rebuild
相关的 child
。 我们知道, flutter
中 Widget
被标识为了 @immutable
,即是不可变的,那么所谓的状态发生变化就意味着 InheriteWidget
重新构建,由于前面代码中在 InheriteWidget
构造时同时也构造的其 child
对象,因此当 InheriteWidget
重新构建时也会导致 child
跟着重新构建,这样也就失去了 “rebuild相关的child”
的意义,
也就是说,要想特性2生效,需要保证 InheriteWidget
节点下的树不会被重新构建。
5. 解决方法1:使用 const Widget
将 InheriteWidget
的 child
转化为 const
,这样即使在重建 InheriteWidget
时,由于其 child
得到的是同一个对象,也就不会导致这个子树重建,选择性 reBuild
也就得到了保证。但是由于 const
特性,相关的参数也必须是常量,因此需要重写或修改的代码量相对较多,因此更推荐 解决方法2
的做法,这个方法在后面回写
1. const demo 01,发现问题
1. 代码结构
2. 效果图
WidgeA
, WidgeB
, FlatButton
是处于同一级别的
从下图可以看到 当我点击了 click me
, widgetB
并不会被 rebuild
, 但是 WidgeA
和 FlatButton
会 rebuild
,这样解决了 WidgeB rebuild
的问题,但是 FlateButton
并不涉及到 页面的数据刷新,如果我想要让 FlatButton
也不 rebuild
呢? 看 const
的 demo02
3. 代码
代码位置: inheritedwidget_const_01.dart
/// 使用 const /// Widget A ,FlatButton rebuild, Widget B no rebuild class InheritedWidgetConst01 extends StatefulWidget { @override State<StatefulWidget> createState() { return InheritedWidgetConst01State(); } } class InheritedWidgetConst01State extends State<InheritedWidgetConst01> { int tmpData = 0; @override Widget build(BuildContext context) { print('InheritedWidgetTest02 build'); return Scaffold( body: Center( child: ShareInherited( data: tmpData, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const WidgetA(), const WidgetB(), FlatButton( child: Text("Click me"), onPressed: () { setState(() { print('onPressed'); tmpData += 1; }); }, ), ], ), ), ), ); } } class ShareInherited extends InheritedWidget { final int data; ShareInherited({this.data, @required Widget child}) : super(child: child) { print('ShareInherited construct'); } @override bool updateShouldNotify(ShareInherited oldWidget) { bool result = oldWidget.data != this.data; print('ShareInherited updateShouldNotify result = $result'); return result; } static ShareInherited of(BuildContext context) { return context.inheritFromWidgetOfExactType(ShareInherited); } } class WidgetA extends StatelessWidget { const WidgetA(); @override Widget build(BuildContext context) { print('WidgetA build'); int data = ShareInherited.of(context).data; return Text('WidgetA data = $data'); } } class WidgetB extends StatelessWidget { const WidgetB(); @override Widget build(BuildContext context) { print('WidgetB build'); return Text('WidgetB'); } } 复制代码
2. const demo 02,继续发现问题
1. 代码结构
2. 效果图
你会发现, WidgeA
和 WidgeC
还是 rebuild
, 要解决这个问题,就需要用到 文章顶部提到的 ancestorWidgetOfExactType
了,看 const demo 03,终极写法
3. 代码
代码位置 inheritedwidget_const_02.dart
/// 使用 const /// Widget A ,Widget C rebuild, Widget B no rebuild class InheritedWidgetConst02 extends StatefulWidget { @override State<StatefulWidget> createState() { return InheritedWidgetConst02State(); } } class InheritedWidgetConst02State extends State<InheritedWidgetConst02> { int tmpData = 0; void addItem(){ setState(() { tmpData++; }); } @override Widget build(BuildContext context) { print('InheritedWidgetTest02 build'); return Scaffold( body: Center( child: ShareInherited( data: tmpData, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const WidgetA(), const WidgetB(), WidgetC(), ], ), state: this, ), ), ); } } class ShareInherited extends InheritedWidget { final int data; final InheritedWidgetConst02State state; ShareInherited({this.data, @required Widget child,this.state}) : super(child: child) { print('ShareInherited construct'); } @override bool updateShouldNotify(ShareInherited oldWidget) { bool result = oldWidget.data != this.data; print('ShareInherited updateShouldNotify result = $result'); return result; } static ShareInherited of(BuildContext context) { return context.inheritFromWidgetOfExactType(ShareInherited); } } class WidgetA extends StatelessWidget { const WidgetA(); @override Widget build(BuildContext context) { print('WidgetA build'); int data = ShareInherited.of(context).data; return Text('WidgetA data = $data'); } } class WidgetB extends StatelessWidget { const WidgetB(); @override Widget build(BuildContext context) { print('WidgetB build'); return Text('WidgetB'); } } class WidgetC extends StatefulWidget { @override _WidgetCState createState() => _WidgetCState(); } class _WidgetCState extends State<WidgetC> { @override Widget build(BuildContext context) { print('Widge C build'); InheritedWidgetConst02State state = ShareInherited.of(context).state; return FlatButton( child: Text("Click me"), onPressed: () { setState(() { print('onPressed'); state.addItem(); }); }, ); } } 复制代码
3. const demo 03,终极写法
1. 代码结构
2. 效果图
ShareInherited
的 of
方法 ,增加了 是否 rebuild
的参数 你会发现 ,现在只有 WidgeA
会 rebuild
,完美啊
static ShareInherited of([BuildContext context, bool rebuild = true]) { return (rebuild ? context.inheritFromWidgetOfExactType(ShareInherited) : context.ancestorWidgetOfExactType(ShareInherited) ); } 复制代码
3. 代码
代码位置 inheritedwidget_const_03.dart
/// 使用 const /// Widget A rebuild, Widget B Widget C no rebuild class InheritedWidgetConst03 extends StatefulWidget { @override State<StatefulWidget> createState() { return InheritedWidgetConst03State(); } } class InheritedWidgetConst03State extends State<InheritedWidgetConst03> { int tmpData = 0; void addItem() { setState(() { tmpData++; }); } @override Widget build(BuildContext context) { print('InheritedWidgetTest02 build'); return Scaffold( body: Center( child: ShareInherited( data: tmpData, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const WidgetA(), const WidgetB(), const WidgetC(), ], ), state: this, ), ), ); } } class ShareInherited extends InheritedWidget { final int data; final InheritedWidgetConst03State state; ShareInherited({this.data, @required Widget child, this.state}) : super(child: child) { print('ShareInherited construct'); } @override bool updateShouldNotify(ShareInherited oldWidget) { bool result = oldWidget.data != this.data; print('ShareInherited updateShouldNotify result = $result'); return result; } static ShareInherited of([BuildContext context, bool rebuild = true]) { return (rebuild ? context.inheritFromWidgetOfExactType(ShareInherited) : context.ancestorWidgetOfExactType(ShareInherited) ); } } class WidgetA extends StatelessWidget { const WidgetA(); @override Widget build(BuildContext context) { print('WidgetA build'); int data = ShareInherited .of(context) .data; return Text('WidgetA data = $data'); } } class WidgetB extends StatelessWidget { const WidgetB(); @override Widget build(BuildContext context) { print('WidgetB build'); return Text('WidgetB'); } } class WidgetC extends StatelessWidget { const WidgetC(); @override Widget build(BuildContext context) { print('Widge C build'); InheritedWidgetConst03State state = ShareInherited.of(context,false).state; return FlatButton( child: Text("Click me"), onPressed: () { print('onPressed'); state.addItem(); }, ); } } 复制代码
6. 解决方法2:上移 Child
对象到 InheriteWidget
的 Parent Widget
1. out demo 01,发现问题
1. 代码结构
2. 效果图
具体看代码吧,稍显复杂 ,这边命名不是很规范,懒得改了, 太累了写 demo
,看代码可以知道
class ShareInherited extends StatelessWidget 复制代码
这里的 ShareInherited
是一个 StatelessWidget
,也就是 上移了 Child
对象到 InheriteWidget
的 Parent Widget
class _ShareInherited extends InheritedWidget 复制代码
而 _ShareInherited
才是 具体的 InheritedWidget
看下图可知 Widget A ,FlatButton rebuild, Widget B no rebuild
这时候我们 一样的 把 FlatButton
放到 WidgetC
然后上移到 InheriteWidget
的 Parent Widget
看能不能实现让 WidgeC
no rebuild
3. 代码
代码位置 inheritedwidget_out_01.dart
/// 上移`Child`对象到`InheriteWidget`的`Parent Widget` /// Widget A ,FlatButton rebuild, Widget B no rebuild class InheritedWidgetOut01 extends StatefulWidget { @override State<StatefulWidget> createState() { return InheritedWidgetOut01State(); } } class InheritedWidgetOut01State extends State<InheritedWidgetOut01> { @override Widget build(BuildContext context) { return Scaffold( body: MyWidget( Column( children: <Widget>[ WidgetA(), WidgetB() ], ) ), ); } } class MyWidget extends StatefulWidget { final Widget child; MyWidget(this.child); @override _MyWidgetState createState() => _MyWidgetState(); } class _MyWidgetState extends State<MyWidget> { int tempData = 0; @override Widget build(BuildContext context) { return ShareInherited( data: tempData, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ widget.child, FlatButton( child: Text("Click me"), onPressed: () { setState(() { print('onPressed'); tempData += 1; }); }, ) ], ), ), ); } } class ShareInherited extends StatelessWidget { final int data; final Widget child; ShareInherited({ Key key, this.data, this.child }): assert(child != null), assert(data != null), super(key: key); static int of(BuildContext context) { final _ShareInherited inheritedTheme = context.inheritFromWidgetOfExactType(_ShareInherited); return inheritedTheme.shareInherited.data; } @override Widget build(BuildContext context) { return _ShareInherited(shareInherited:this , child: child,); } } class _ShareInherited extends InheritedWidget{ final ShareInherited shareInherited; _ShareInherited({ Key key, @required this.shareInherited, @required Widget child, }):assert(shareInherited != null), super(key: key, child: child); @override bool updateShouldNotify(_ShareInherited oldWidget) { return shareInherited.data != oldWidget.shareInherited.data; } } class WidgetA extends StatelessWidget { @override Widget build(BuildContext context) { print('WidgetA build'); int data = ShareInherited.of(context); return Text('WidgetA data = $data'); } } class WidgetB extends StatelessWidget { @override Widget build(BuildContext context) { print('WidgetB build'); return Text('WidgetB'); } } 复制代码
2. out demo 02,继续发现问题
1. 代码结构
2. 效果图
你会发现 Widget A ,Widget C rebuild, Widget B no rebuild
如果想要 让 Widge C no rebuild,看 out demo 03
3. 代码
代码位置 inheritedwidget_out_02.dart
/// 上移`Child`对象到`InheriteWidget`的`Parent Widget` /// Widget A ,Widget C rebuild, Widget B no rebuild class InheritedWidgetOut02 extends StatefulWidget { @override _InheritedWidgetOut02State createState() => new _InheritedWidgetOut02State(); } class _InheritedWidgetOut02State extends State<InheritedWidgetOut02> { @override Widget build(BuildContext context) { return new MyInheritedWidget( child: new Scaffold( appBar: new AppBar( title: new Text('Title'), ), body: Center( child: new Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[new WidgetA(), new WidgetB(), new WidgetC()], ), ), ), ); } } class MyInheritedWidget extends StatefulWidget { MyInheritedWidget({ Key key, this.child, }) : super(key: key); final Widget child; @override MyInheritedWidgetState createState() => new MyInheritedWidgetState(); static MyInheritedWidgetState of([BuildContext context]) { return (context.inheritFromWidgetOfExactType(_MyInherited) as _MyInherited).data; // 通过从 MyInheritedWidget 的 context 得到树结构来返回第一个 MyInheritedWidgetState } } class MyInheritedWidgetState extends State<MyInheritedWidget> { int tempData = 0; /// Helper method to add an Item void addItem() { setState(() { tempData++; }); } @override Widget build(BuildContext context) { return new _MyInherited( data: this, child: widget.child, ); } } class _MyInherited extends InheritedWidget { _MyInherited({ Key key, @required Widget child, @required this.data, }) : super(key: key, child: child); final MyInheritedWidgetState data; @override bool updateShouldNotify(_MyInherited oldWidget) { return true; } } class WidgetA extends StatelessWidget { @override Widget build(BuildContext context) { print('Widget A build'); final MyInheritedWidgetState state = MyInheritedWidget.of(context); return Text('WidgetA data = ${state.tempData}'); } } class WidgetB extends StatelessWidget { @override Widget build(BuildContext context) { print('Widget B build'); return Text('WidgetB'); } } class WidgetC extends StatefulWidget { @override _WidgetCState createState() => _WidgetCState(); } class _WidgetCState extends State<WidgetC> { @override Widget build(BuildContext context) { print('Widget C build'); final MyInheritedWidgetState state = MyInheritedWidget.of(context); return RaisedButton( child: Text("Click me"), onPressed: () { print('onPressed'); state.addItem(); }, ); } } 复制代码
3. out demo 03,终极写法
1. 代码结构
2. 效果图
因为这个 demo
的 Perfomance
界面展示不够形象,就直接展示输出 log
查看结果比较形象
可以发现 Widget A rebuild, Widget B Widget C no rebuild ,完美啊 ,写到这里已经要吐了
3. 代码
代码位置 inheritedwidget_out_03.dart
/// 上移`Child`对象到`InheriteWidget`的`Parent Widget` /// Widget A rebuild, Widget B Widget C no rebuild class InheritedWidgetOut03 extends StatefulWidget { @override _InheritedWidgetOut03State createState() => new _InheritedWidgetOut03State(); } class _InheritedWidgetOut03State extends State<InheritedWidgetOut03> { @override Widget build(BuildContext context) { return new MyInheritedWidget( child: new Scaffold( appBar: new AppBar( title: new Text('Title'), ), body: Center( child: new Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[new WidgetA(), new WidgetB(), new WidgetC()], ), ), ), ); } } class MyInheritedWidget extends StatefulWidget { MyInheritedWidget({ Key key, this.child, }) : super(key: key); final Widget child; @override MyInheritedWidgetState createState() => new MyInheritedWidgetState(); static MyInheritedWidgetState of( [BuildContext context, bool rebuild = true]) { return (rebuild ? context.inheritFromWidgetOfExactType(_MyInherited) as _MyInherited : context.ancestorWidgetOfExactType(_MyInherited) as _MyInherited) .data; // 通过从 MyInheritedWidget 的 context 得到树结构来返回第一个 MyInheritedWidgetState } } class MyInheritedWidgetState extends State<MyInheritedWidget> { int tempData = 0; /// Helper method to add an Item void addItem() { setState(() { tempData++; }); } @override Widget build(BuildContext context) { return new _MyInherited( data: this, child: widget.child, ); } } class _MyInherited extends InheritedWidget { _MyInherited({ Key key, @required Widget child, @required this.data, }) : super(key: key, child: child); final MyInheritedWidgetState data; @override bool updateShouldNotify(_MyInherited oldWidget) { return true; } } class WidgetA extends StatelessWidget { @override Widget build(BuildContext context) { print('Widget A build'); final MyInheritedWidgetState state = MyInheritedWidget.of(context); return Text('WidgetA data = ${state.tempData}'); } } class WidgetB extends StatelessWidget { @override Widget build(BuildContext context) { print('Widget B build'); return Text('WidgetB'); } } class WidgetC extends StatefulWidget { @override _WidgetCState createState() => _WidgetCState(); } class _WidgetCState extends State<WidgetC> { @override Widget build(BuildContext context) { print('Widget C build'); final MyInheritedWidgetState state = MyInheritedWidget.of(context, false); return RaisedButton( child: Text("Click me"), onPressed: () { print('onPressed'); state.addItem(); }, ); } } 复制代码
7. 两种解决方法,在源码中的应用
方法1 : 可以查看 TickerMode
这个类
方法2: 可以查看 Theme
类
以上所述就是小编给大家介绍的《Flutter - 数据共享,通信,状态管理 - 01 - InheritedWidget》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- javascript – 有可能使用angularJs将状态从状态传递到状态吗?
- 前端状态管理与有限状态机
- 如何可视化需求状态和团队状态?
- 给 DSL 开个脑洞:无状态的状态机
- 基于有限状态机的广告状态管理方案及实现
- 基于有限状态机的广告状态管理方案及实现
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。