Flutter-InheritedWidget-数据分发

InheritedWidget是一个特殊的widget,可以存储和获取数据,子组件可以获取到存储的数据,常用的 MediaQueryTheme 就是继承了 InheritedWidget

 

inherited widget 定义

  • 数据传递和数据共享
  • 实现数据分发:在不同的widget中获得共同的数据
  • 对其他Widget的一个实现或者补充
  • 例如:Theme.of(context)返回你能拿到一个ThemeData
  • 并使用其内部自定义的属性改变你当前widget的显示效果

相信大家很熟悉这段代码 MediaQuery.of(context).size.width;

class MediaQuery extends InheritedWidget {
    const MediaQuery({
      Key key,
      @required this.data,
      @required Widget child,
    }) : assert(child != null),
         assert(data != null),
         super(key: key, child: child);
  
    ///...
    final MediaQueryData data;
    ///...
  
    static MediaQueryData of(BuildContext context, { bool nullOk = false }) {
    ///...
  }
}

直接上案例:如何在不同的widget中获得共同的数据

购物车商品数量添加和减少

购物车商品数量添加和减少

1.创建一个Item模型,用于保存购物车的数量

class Item {
  String reference;

  Item(this.reference);
}

2.创建一个InheritedWidget

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 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;
  }
}

3.创建一个MyInheritedWidgetState 来管理全局状态

class MyInheritedWidgetState extends State<MyInheritedWidget> {
  List<Item> _items = <Item>[];

  int get itemsCount => _items.length;

  //添加Item
  void addItem(String reference) {
    setState(() {
      _items.add(new Item(reference));
    });
  }
  //移除Item
  void removeItem() {
    setState(() {
      if (_items.length > 0){
        _items.removeLast();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return new _MyInherited(
      data: this,
      child: widget.child,
    );
  }
}

4.组合使用

关键代码

// 防止WidgetA被rebuild
final MyInheritedWidgetState state = MyInheritedWidget.of(context, false); 
class MyTree extends StatefulWidget {
  @override
  _MyTreeState createState() => new _MyTreeState();
}

class _MyTreeState extends State<MyTree> {
  @override
  Widget build(BuildContext context) {
    return MyInheritedWidget(
      child: new Scaffold(
        appBar: new AppBar(
          title: new Text('Title'),
        ),
        body: new Column(
          children: <Widget>[
            new WidgetA(),
            new WidgetD(),
            new Container(
              child: new Row(
                children: <Widget>[
                  new Icon(Icons.shopping_cart),
                  new WidgetB(),
                  new WidgetC(),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class WidgetA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final MyInheritedWidgetState state = MyInheritedWidget.of(context, false);  // 防止WidgetA被rebuild
    return new Container(
      child: new RaisedButton(
        child: new Text('Add Item'),
        onPressed: () {
          state.addItem('new item');
        },
      ),
    );
  }
}

class WidgetB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final MyInheritedWidgetState state = MyInheritedWidget.of(context);
    return new Text('${state.itemsCount}');
  }
}

class WidgetC extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Text('I am Widget C');
  }
}

class WidgetD extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final MyInheritedWidgetState state = MyInheritedWidget.of(context, false);  // 防止WidgetA被rebuild
    return new Container(
      child: new RaisedButton(
        child: new Text('Remove Item'),
        onPressed: () {
          state.removeItem();
        },
      ),
    );
  }
}

补充

1.inheritFromWidgetOfExactType

  • 获取最近的给定类型的Widget,该widget必须是InheritedWidget的子类,并向该widget注册传入的context,当该widget改变时,这个context会重新构建以便从该widget获得新的值。这就是child向InheritedWidget注册的方法。
  • 继承的 widget 将在更改时触发重新构建

2.ancestorWidgetOfExactType

  • 适用于交互事件处理程序(例如手势回调)或执行一次性任务,例如 断言 您拥有或不具有作为特定类型的父 widget 。 widget 的构建方法的返回值不应该依赖于该方法返回的值,因为如果该方法的返回值发生更改,构建上下文将 不会重新生成 。这可能会导致生成方法中使用的数据发生更改,但是没有重新生成 widget 。
  • 可以用来获取父 widget 的一些信息

Flutter篇



作者:StevenHu_Sir
链接:https://www.jianshu.com/p/377e4fb11649
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值