Flutter中的InheritedWidget
1.InheritedWidget是什么?
InheritedWidget是Flutter中非常重要的一个功能型组件,它提供了一种数据在widget树中从上到下传递、共享的方式,比如我们在应用的根widget中通过InheritedWidget共享了一个数据,那么我们便可以在任意子widget中来获取该共享的数据!这个特性在一些需要在widget树中共享数据的场景中非常方便!如Flutter SDK中正是通过InheritedWidget来共享应用主题(Theme)和Locale (当前语言环境)信息的。
InheritedWidget和React中的context功能类似,和逐级传递数据相比,它们能实现组件跨级传递数据。InheritedWidget的在widget树中数据传递方向是从上到下的,这和通知Notification(将在下一章中介绍)的传递方向正好相反。
2.如何使用InheritedWidget
1)、创建一个类继承自Inheritedwidget
class InheritedContext extends InheritedWidget{ final InheritedTestModel inheritedTestModel; InheritedContext({ Key key, @required this.inheritedTestModel, @required Widget child}): super(key: key, child: child);static InheritedContext of(BuildContext context) { return context.dependOnInheritedWidgetOfExactType<InheritedContext>(); } @override bool updateShouldNotify(InheritedContext oldWidget) { return inheritedTestModel != oldWidget.inheritedTestModel; }}
2)、InheritedTestModel类为数据容器(这里定义了一个List<int>数据源)
class InheritedTestModel{ final List _list; InheritedTestModel(this._list); List getList(){ return _list; }}
class ArrayListData{ static List _list;static List getListData(){ _list = new List(); _list.add(1); _list.add(2); _list.add(3); _list.add(4);return _list; }}class InheritedContext extends InheritedWidget{ final InheritedTestModel inheritedTestModel; InheritedContext({ Key key, @required this.inheritedTestModel, @required Widget child}): super(key: key, child: child);static InheritedContext of(BuildContext context) { return context.dependOnInheritedWidgetOfExactType<InheritedContext>(); } @override bool updateShouldNotify(InheritedContext oldWidget) { return inheritedTestModel != oldWidget.inheritedTestModel; }}
2)、InheritedTestModel类为数据容器(这里定义了一个List<int>数据源)
class InheritedTestModel{ final List _list; InheritedTestModel(this._list); List getList(){ return _list; }}
class ArrayListData{ static List _list;static List getListData(){ _list = new List(); _list.add(1); _list.add(2); _list.add(3); _list.add(4);return _list; }}class InheritedContext extends InheritedWidget{ final InheritedTestModel inheritedTestModel; InheritedContext({ Key key, @required this.inheritedTestModel, @required Widget child}): super(key: key, child: child);static InheritedContext of(BuildContext context) { return context.dependOnInheritedWidgetOfExactType<InheritedContext>(); } @override bool updateShouldNotify(InheritedContext oldWidget) { return inheritedTestModel != oldWidget.inheritedTestModel; }}
2)、InheritedTestModel类为数据容器(这里定义了一个List<int>数据源)
class InheritedTestModel{ final List _list; InheritedTestModel(this._list); List getList(){ return _list; }}
class ArrayListData{ static List _list;static List getListData(){ _list = new List(); _list.add(1); _list.add(2); _list.add(3); _list.add(4);return _list; }}
2)、InheritedTestModel类为数据容器(这里定义了一个List<int>数据源)
class InheritedTestModel{ final List _list; InheritedTestModel(this._list); List getList(){ return _list; }}
class ArrayListData{ static List _list;static List getListData(){ _list = new List(); _list.add(1); _list.add(2); _list.add(3); _list.add(4);return _list; }}
3)、定义一个Widget 使用 InheritedContext类的数据 InheritedTestModel
class ListDemo extends StatefulWidget{ @override State createState() { return new ListDemoState(); }}class ListDemoState extends State<ListDemo>{List _list; InheritedTestModel _inheritedTestModel; Timer _timer; Duration oneSec = const Duration(seconds: 1); @override void initState() { _list = ArrayListData.getListData(); _inheritedTestModel = new InheritedTestModel(_list); _timer = Timer.periodic(oneSec, (timer) { _doTimer(); }); } void _doTimer() { for(int i = 0; i < _list.length; i++){ _list[i] = _list[i]+ 1; } setState(() { _inheritedTestModel = new InheritedTestModel(_list); }); }Widget _buildBody() { return Container(child: ListDemo2(), ); } @override Widget build(BuildContext context) { return InheritedContext(inheritedTestModel: _inheritedTestModel, child: Scaffold(appBar: AppBar(title: Text("ListDemo"), actions: <Widget>[ IconButton(icon: Icon(Icons.add), ) ],), body: _buildBody(), ), ); } @override void dispose() { super.dispose();if (_timer != null) { _timer.cancel(); } }}
4)、在ListDemo中通过Timer更新InheritedTestModel 中的数据,然后再下一个Widget中获取更新的数据作为展示
class ListDemo2 extends StatefulWidget{ @override State createState() { return new ListDemoState2(); }}class ListDemoState2 extends State<ListDemo2>{InheritedTestModel _inheritedTestModel; Widget _buildListItem(BuildContext context,int index) { return Container(height: 50, width: 100, alignment: Alignment.center, child: Text(_inheritedTestModel.getList()[index].toString()), ); }Widget _buildBody() { _inheritedTestModel = InheritedContext.of(context).inheritedTestModel;return Container(child: ListView.builder(itemBuilder:(context, index)=>_buildListItem(context,index),itemCount: _inheritedTestModel.getList().length,), ); } @override Widget build(BuildContext context) { return _buildBody(); }}
这样就可以在父widget中更新数据,子View不需任何操作直接从数据容器InheritedTestModel 中获取到更新后的新数据
这是一个数据共享的简单的例子