简单一点说html
- inhertedwidget 是一个widget,跟其余widget不同的地方是,他能够在他所持有的child中共享本身的数据。如Theme。
- 应用场景:app的复杂度愈来愈大,对于数据之间的传递,若是都是根据dic或者model做为widget内部的参数传递,是不友好的方式。正常的想法,此时应该有个数据中心,或eventbus,用于数据传递和取用,而在flutter中是inhertwidget
- 实现: 内部实现数据更新,自动通知的方式,从而自动刷新界面
- 写法: 见下面例子
对于赶时间的同窗看到这里就能够回去搬砖了。下面留给还有五分钟时间浏览的同窗。数据库
google 在flutter widget of the week
中介绍 inheritedwidget
, 短短的两个简短的视频,让人看到了flutter的用心,外语通常的我也能把概念看得个大概。可是对于真正使用其上手开发的同窗总以为离实际开发距离有点远,仍是得编写一下例子才能理解更深一点。api
做为一名高效的搬砖工,先看看它说了啥bash
当应用变得更大时,小部件树,变得更复杂,传递和访问数据,会变得很麻烦。 若是你有四个或五个小部件一个接一个地嵌套, 而且您须要从顶部获取一些数据。将它添加到全部这些构造函数中,以及全部这些构建方法。网络
然而我只是想到达widget来获取数据。 不想一级一级传递数据。怎么办?幸运的是,有一个小部件类型容许这样。 它叫作InheritedWidget。app
class FrogColor extends InheritedWidget {
const FrogColor({
Key key,
@required this.color,
@required Widget child,
}) : assert(color != null),
assert(child != null),
super(key: key, child: child);
final Color color;
static FrogColor of(BuildContext context) {
return context.inheritFromWidgetOfExactType(FrogColor) as FrogColor;
}
@override
bool updateShouldNotify(FrogColor old) => color != old.color;
}
复制代码
class TestWidgetA extends StatelessWidget {
@override
Widget build(BuildContext context) {
final inheritedContext = FrogColor.of(context);
return new Padding(
padding: const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0),
child: Container(
color: inheritedContext.color,
height: 100,
width: 100,
child: Text('第一个widget'),
));
}
}
class TestWidgetB extends StatelessWidget {
@override
Widget build(BuildContext context) {
final inheritedContext = FrogColor.of(context);
return new Padding(
padding: const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0),
child: Container(
color: inheritedContext.color,
height: 50,
width: 50,
child: Text('第二个widget'),
));
}
}
复制代码
class TestWidgetC extends StatefulWidget {
TestWidgetC({Key key}) : super(key: key);
_TestWidgetCState createState() => _TestWidgetCState();
}
class _TestWidgetCState extends State<TestWidgetC> {
@override
Widget build(BuildContext context) {
final inheritedContext = FrogColor.of(context);
// print(" 重建c CCC ");
return Container(
child: Container(
color: inheritedContext.color,
height: 200,
width: 200,
child: prefix0.Column(
children: <Widget>[
Text("第三个widget"),
],
),
));
}
@override
void didChangeDependencies() {
print(" 更改依赖 CCC ");
super.didChangeDependencies();
}
}
复制代码
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
Color color = Color.fromARGB(0, 0xff, 0xdd, 0xdd);
Color color2 = Color.fromARGB(0, 0xff, 0xdd, 0xdd);
void _incrementCounter() {
setState(() {
_counter = (_counter + 20) % 255;
Color color = Color.fromARGB(_counter, 0xff, 0xdd, 0xdd);
this.color = color;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
new FrogColor(
color: this.color,
color2: this.color2,
child: Column(
children: <Widget>[
new TestWidgetA(),
new TestWidgetB(),
new TestWidgetC()
],
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
复制代码
本段代码实现了点击+号,数字增长,而且两个widget的颜色加深less
效果图以下ide
它为您调用InheritWidget的精确类型方法。函数
static FrogColor of(BuildContext context) {
return context.inheritFromWidgetOfExactType(FrogColor) as FrogColor;
}
复制代码
例子中FrogColor 里面的color就是一个final类型,不能够改变ui
只能替换InheritedWidget的字段,经过重建
整个widget 树。 这个很重要!!! 只是意味着它没法从新分配
。 可是并不意味着它不能在内部改变。
inhertedwidget改变了就会触发,didChangeDependencies,对于耗时操做的业务如网络请求来讲能够放置这里。
从上例中能够作个试验,在widgetC中移除 FrogColor.of(context)
这句话,能够看到,颜色很差随着按钮点击变色,另外也不会调用didChangeDependencies
这个方法了。可是widgetc仍是会走build方法。
能够印证两点,widget会重建,可是state不会重建,didChangeDespendice方法调用的时机是其依赖的上下文内容改变。
Theme其实是一种InheritedWidget。 Scaffold,Focus Scope等等也是如此。
附加服务对象到InheritedWidget。 如开发数据库的包装器
Web API的代理或资产提供者。 服务对象能够有本身的内部状态。 它能够启动网络呼叫,任何事情。
继承自Inhertedwidget,其值能够是被监听的,而且只要值发送通知就会通知依赖者。
使用场景有 ChangeNotifier
或ValueNotifier
abstract class InheritedNotifier<T extends Listenable> extends InheritedWidget {
const InheritedNotifier({
Key key,
this.notifier,
@required Widget child,
}) : assert(child != null),
super(key: key, child: child);
@override
bool updateShouldNotify(InheritedNotifier<T> oldWidget) {
return oldWidget.notifier != notifier;
}
@override
_InheritedNotifierElement<T> createElement() => _InheritedNotifierElement<T>(this);
}
复制代码
继承自 Inertedwidget的,容许客户端订阅值的子部分的更改。
就比InertedWidget多了一个必要方法updateShouldNotifyDependent
,表示能够根据,部份内容的改变发送依赖变动通知。
class ABModel extends InheritedModel<String> {
ABModel({this.a, this.b, Widget child}) : super(child: child);
final int a;
final int b;
@override
bool updateShouldNotify(ABModel old) {
return a != old.a || b != old.b;
}
@override
bool updateShouldNotifyDependent(ABModel old, Set<String> aspects) {
return (a != old.a && aspects.contains('a')) ||
(b != old.b && aspects.contains('b'));
}
// ...
}
复制代码
一图说明
参考