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

跨组件状态共享

作者: 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