在flutter开发中,我们通常只管理、操作widget,framework也没有提供方便的接口来对这些对象进行直接操作,我们通常接触到的界面绘制入口,只有build方法,这就给我们的跨层级操作UI造成很大的困难。虽然我们已经知道可以通过flutter的渲染树来获取到指定对象,实现UI更新,但这不优雅。flutter提供了一个更优雅的方式-InheritedWidget。
InheritedWidget
InheritedWidget 是带有通知属性的widget
,framework有对其做特殊处理,官方描述如下:
Base class for widgets that efficiently propagate information down the tree.
简单的说,我们可以利用inheritedWidget
来实现响应式的UI界面构建。
示例
一:创建模型对象,管理数据
class ALRootModel {
ALRootModel({this.count});
final int count;
}
二:创建InheritedWidget 类,分发消息
class ALRootInheritWideget extends InheritedWidget {
ALRootInheritWideget({Key key, this.child, this.model})
: super(key: key, child: child);
final Widget child;
final ALRootModel model;
//便利方法
static ALRootInheritWideget of(BuildContext context) {
return (context.inheritFromWidgetOfExactType(ALRootInheritWideget)
as ALRootInheritWideget);
}
//消息更新,触发消息分发
@override
bool updateShouldNotify(ALRootInheritWideget oldWidget) {
return this.model != oldWidget.model;
}
}
三:使用InheritedWidget
class _InheritWidegetTestPageState extends State<InheritWidegetTestPage> {
ALRootModel _model;
var _count = 1;
@override
void initState() {
super.initState();
_model = ALRootModel(count: _count);
}
void _didHitBtn() {
setState(() {
_count++;
// 触发消息更新
_model = ALRootModel(count: _count);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('ALRootInheritWideget'),
),
body: ALRootInheritWideget(
model: _model,
child: Container(
padding: EdgeInsets.all(32.0),
child: Center(
child: Column(
children: <Widget>[
Text('我是计数器$_count'),
SizedBox(height: 30,),
FlatButton(
child: Text('hit me'),
color: Colors.greenAccent,
onPressed:_didHitBtn
),
SizedBox(height: 30,),
ClassA()
],
),
),
),
));
}
}
四:接收消息,并完成UI更新
class ClassA extends StatefulWidget {
_ClassAState createState() => _ClassAState();
}
class _ClassAState extends State<ClassA> {
@override
Widget build(BuildContext context) {
ALRootModel model = ALRootInheritWideget.of(this.context).model;
return Container(
child: Container(
color: Colors.greenAccent,
alignment: Alignment.center,
constraints: BoxConstraints(
maxWidth: double.infinity,
minWidth: 200.0,
maxHeight: 300,
minHeight: 200.0),
child: Text('我也是计数器${model.count}')),
);
}
}
注意
- InheritedWidget只能管理子widget消息分发,因此
ALRootInheritWideget.of(this.context).model;
只能在子widget中才能获取到实例对象。 - InheritedWidget作为子widget的dependency,可以自子widget对应的生命周期方法中做自定义处理。