美文网首页
跨组件状态共享

跨组件状态共享

作者: Harely | 来源:发表于2020-05-01 16:57 被阅读0次
    import 'dart:collection';
    import 'dart:typed_data';
    
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    
    // 一个通用的InheritedWidget,保存任需要跨组件共享的状态
    class InheritedProvider<T> extends InheritedWidget {
      //共享状态使用泛型
      final T data;  
    
    
      InheritedProvider({@required this.data, Widget child}) : super(child: child);
      
      @override
      //在此简单返回true,则每次更新都会调用依赖其的子孙节点的`didChangeDependencies`。
      bool updateShouldNotify(InheritedProvider<T> oldWidget) {
        return true;
      }
      
    }
    
    
    
    Type _typeOf<T>() => T;
    class ChangeNotifierProvider<T extends ChangeNotifier> extends StatefulWidget {
      final Widget child;
      final T data;
        
    
      ChangeNotifierProvider({
        Key key,
        this.data,
        this.child,
      });
    
      //定义一个便捷方法,方便子树中的widget获取共享数据
      static T of<T> (BuildContext context) {
        final type = _typeOf<InheritedProvider<T>>();
        //final provider = context.inheritFromWidgetOfExactType(type) as InheritedProvider<T>;
        //final provider = context.dependOnInheritedWidgetOfExactType(aspect: type) as InheritedProvider<T>;
        final provider = context.dependOnInheritedWidgetOfExactType<InheritedProvider<T>>();
        print("商品的Model是:${(provider.data as CartModel).totalPrice}");
        return provider.data;
      }
    
      @override
      _ChangeNotifierProviderState<T> createState() {
        return _ChangeNotifierProviderState<T>();
      }
      
    }
    
    /*
    * _ChangeNotifierProviderState 主要作用就是监听到共享状态(model)改变时重新构建Widget树
    * 
    */
    class _ChangeNotifierProviderState<T extends ChangeNotifier> extends State<ChangeNotifierProvider<T>> {
      
      ///如果数据发生变化(model类调用了notifyListeners),重新构建InheritedProvider
      //void update() => setState(() => {});
      void update() {
        //build方法会被执行
        setState(() => {});
      }
      
    
      @override
      void didUpdateWidget(ChangeNotifierProvider<T> oldWidget) {
        // 当Provider更新时,如果新旧数据不"==",则解绑旧数据监听,同时添加新数据监听
        if (widget.data != oldWidget.data) {
          oldWidget.data.removeListener(update);
          widget.data.addListener(update);
        }
        super.didUpdateWidget(oldWidget);
      }
    
      @override
      void initState() {
        // 给model添加监听器
        widget.data.addListener(update);
        super.initState();
      }
    
      @override
      void dispose() {
        // 移除model的监听器
        widget.data.removeListener(update);
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return InheritedProvider<T>(
          data: widget.data,
          child: widget.child,
        );
      }
      
    }
    
    
    /*
    * 定义一个Item类,用于表示商品信息 
    *
    */
    class Item {
      //商品单价
      double price;
      // 商品份数
      int count;
    
      Item(this.price, this.count);
    }
    
    
    /*
    * 定义一个保存购物车内商品数据的CartModel类
    * CartModel即要跨组件共享的model类
    */
    class CartModel extends ChangeNotifier {
      //用于保存购物车中商品列表
      final List<Item> _items = [];
      ///禁止改变购物车里的商品信息
      UnmodifiableListView<Item> get items => UnmodifiableListView(_items);
      ///购物车中商品的总价
      double get totalPrice => _items.fold(0, (value, item) => value + item.count * item.price);
    
    
      //将 [item] 添加到购物车。这是唯一一种能从外部改变购物车的方法
      void add(Item item) {
        _items.add(item);
        //通知监听器(订阅者),重新构建InheritedProvider, 更新状态
        notifyListeners();
      }
    }
    
    /*
    * 构建示例页面类:ProviderRoute
    *
    */
    class ProviderRoute extends StatefulWidget {
      @override
      _ProviderRouteState createState() => _ProviderRouteState();
      
    }
    
    class _ProviderRouteState extends State<ProviderRoute> {
      
      
      @override
      Widget build(BuildContext context) {
    
        return Center(
          child:ChangeNotifierProvider<CartModel>(
            data: CartModel(),
            child: Builder(builder: (context) {
              return Column(
                children:<Widget>[
                  Text(""),
                  Text(""),
                  Text(""),
                  Text(""),
                  Builder(builder: (context) {
                    var cart = ChangeNotifierProvider.of<CartModel>(context);
                    return Text("总价: ${cart.totalPrice}");
                  }),
                  Builder(builder: (context) {
                    //在后面优化部分会用到
                    print("RaisedButton build");
                    return RaisedButton(
                      child: Text("添加商品"),
                      onPressed: (){
                        ChangeNotifierProvider.of<CartModel>(context).add(Item(20.0, 1));
                      },
                    );
                  }),
                ],
              );
            }),
          ),
        );
      }
      
    }
    

    效果图:


    购物车价格显示

    相关文章

      网友评论

          本文标题:跨组件状态共享

          本文链接:https://www.haomeiwen.com/subject/ssuqghtx.html