内容简介:可以说是目前 全网 最完整的返回给定类型的最近父
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 开个脑洞:无状态的状态机
- 基于有限状态机的广告状态管理方案及实现
- 基于有限状态机的广告状态管理方案及实现
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。