在flutter開(kāi)發(fā)中,我們通常只管理、操作widget,framework也沒(méi)有提供方便的接口來(lái)對(duì)這些對(duì)象進(jìn)行直接操作,我們通常接觸到的界面繪制入口,只有build方法,這就給我們的跨層級(jí)操作UI造成很大的困難。雖然我們已經(jīng)知道可以通過(guò)flutter的渲染樹(shù)來(lái)獲取到指定對(duì)象,實(shí)現(xiàn)UI更新,但這不優(yōu)雅。flutter提供了一個(gè)更優(yōu)雅的方式-InheritedWidget。
InheritedWidget
InheritedWidget 是帶有通知屬性的widget,framework有對(duì)其做特殊處理,官方描述如下:
Base class for widgets that efficiently propagate information down the tree.
簡(jiǎn)單的說(shuō),我們可以利用inheritedWidget來(lái)實(shí)現(xiàn)響應(yīng)式的UI界面構(gòu)建。
示例
一:創(chuàng)建模型對(duì)象,管理數(shù)據(jù)
class ALRootModel {
ALRootModel({this.count});
final int count;
}
二:創(chuàng)建InheritedWidget 類,分發(fā)消息
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);
}
//消息更新,觸發(fā)消息分發(fā)
@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++;
// 觸發(fā)消息更新
_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('我是計(jì)數(shù)器$_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('我也是計(jì)數(shù)器${model.count}')),
);
}
}
注意
- InheritedWidget只能管理子widget消息分發(fā),因此
ALRootInheritWideget.of(this.context).model;只能在子widget中才能獲取到實(shí)例對(duì)象。 - InheritedWidget作為子widget的dependency,可以自子widget對(duì)應(yīng)的生命周期方法中做自定義處理。