对于flutter的数据共享,我是很懵逼的,真的不如vue和react那么直观明了,果然还是编程思想不够啊,通过根据flutter的官网介绍以及自己超的官网代码有了一点点理解吧。毕竟刚接触,极大的可能理解的不对。。。。。。
1、创建一个类,用于全局保存数据
创建InheritedProvider类后,然后继承flutter自带的数据共享类InheritedWidget,这个类和vue里面的祖孙之间传递数据(provide/inject)的概念是一样的,属于隔代遗传。它接受两个参数,一个是需要保持数据的组件,一个是需要保存的数据,也就是传递组件中的数据。。这点我都看不上它,vue中保存数据直接存在store中,然而此方式是将数据传递给该数据,要是说非要有点关系,也就是vue中通过组件将数据commit到store这点相似。。。。或许flutter也能直接讲全局常量存在该类中,但我还没了解到。。。。。
这个是通过继承InheritedWidget类直接实现数据共享
import 'package:flutter/material.dart';
//用于保存数据共享的数据以及方法
class InheritedProvider<T> extends InheritedWidget {
InheritedProvider({
required Widget child,
required this.data,
}) : super(child: child);
final T data;
@override
bool updateShouldNotify(InheritedProvider<T> old) {
return true;
}
}
2、再创建一个用于通知全局数据改变的类ChangeNotifierProvider
这个类,我觉得它才是重点,继承了上了一类,而且提供了能拿到传递过来的数据的方法of,还提供了对传递数据进行了对比的方法,监听是否更新,既然继承了,说明后期咱们都用不到了InheritedProvider类,只需要往ChangeNotifierProvider类中传递数据和组件就行了,要是那个组件需要点用共享数据,直接饮用该类中of方法即可,上代码。。。。。。看不懂吗????,慢慢啃,我也不懂。。。
import 'package:demo/pages/view/provider/InheritedProvider.dart';
import 'package:flutter/material.dart';
class ChangeNotifierProvider<T extends ChangeNotifier> extends StatefulWidget {
ChangeNotifierProvider({
Key? key,
required this.data,
required this.child,
});
final Widget child;
final T data;
//定义一个便捷方法,方便子树中的widget获取共享数据
static T of<T>(BuildContext context) {
// final type = _typeOf<InheritedProvider<T>>();
final provider =
context.dependOnInheritedWidgetOfExactType<InheritedProvider<T>>();
return provider!.data;
}
@override
_ChangeNotifierProviderState<T> createState() =>
_ChangeNotifierProviderState<T>();
}
class _ChangeNotifierProviderState<T extends ChangeNotifier>
extends State<ChangeNotifierProvider<T>> {
void update() {
//如果数据发生变化(model类调用了notifyListeners),重新构建InheritedProvider
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,
);
}
}
放着不要动,之后就是给它传递数据和组件了。。。。。。下面创建一个例子
3、创建一个管理主页面的数据以及方法CartModel类
该方法里面创建了一个实例,变量为单价和数量,这个功能就是,点击添加数量,总价格也会相应的改变,其实正常写哪有这么多*事,直接写就完了,可是咱们不是要用将这个model类传递给共享嘛,迎着头皮写吧,没办法。。。。。,
import 'dart:collection';
import 'package:flutter/material.dart';
class Item {
Item(this.price, this.count);
double price; //商品单价
int count; // 商品数量
}
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();
}
}
fold方法数据集合元素的折叠也可作为循环使用
4、剩下就是页面中怎么传递数据以使用了
看下面的引入包,只需要引入通知类和model类,将model作为数据传递给ChangeNotifierProvider,然后通过of函数拿到里面的数据,
import 'package:flutter/material.dart';
import './model/CartModel.dart';
import './model/ChangeNotifierProvider.dart';
class ProviderRoute extends StatefulWidget {
@override
_ProviderRouteState createState() => _ProviderRouteState();
}
class _ProviderRouteState extends State<ProviderRoute> {
@override
Widget build(BuildContext context) {
return Center(
//传递需要全局共享的数据CartModel
child: ChangeNotifierProvider<CartModel>(
data: CartModel(),
//将子组件传递给ChangeNotifierProvider类需要传递个上下文context
child: Builder(builder: (context) {
return Column(
children: <Widget>[
Builder(builder: (context) {
//通过of拿到计算出来的总价格,显示在页面上
var cart = ChangeNotifierProvider.of<CartModel>(context);
return Text("总价: ${cart.totalPrice}");
}),
Builder(builder: (context) {
print("ElevatedButton build"); //在后面优化部分会用到
return ElevatedButton(
child: Text("添加商品"),
//调用ChangeNotifierProvider中的add,改变数量
onPressed: () {
//给购物车中添加商品,添加后总价会更新,
ChangeNotifierProvider.of<CartModel>(context)
.add(Item(20.0, 1));
},
);
}),
],
);
}),
),
);
}
}
通过ChangeNotifierProvider.of(context)调用通过ChangeNotifierProvider中的方法。先到这吧,就只能会用了详细参考