在前端开发中组件式开发方式往往都是需要用到各组件之间数据,状态的共享,兄弟组件,父子组件数据共享等。在vue中有vuex,react中有redux;在flutter中,状态共享的工具很多,redux、bloc、Provide以及阿里闲鱼出的fish_redux。本文中先介绍Provide的基本使用。
1. 添加依赖
provide官方已经不升级维护,但是还是可以使用它:https://github.com/google/flutter-provide
- pubspec.yaml添加如下依赖,保存自动拉取依赖
dependencies:
provide: ^1.0.2
2. 创建共享数据Store
笔者目前是前端开发,用的vue,觉得Provide还有点像vuex,所以把共享数据叫Store,其他人叫Model,不过这都不重要,把它看成是一个数据共享源就行。
2.1 在lib下新建一个store文件
新建counter.dart
// counter.dart
import 'package:flutter/material.dart';
class Counter with ChangeNotifier { // with相当于混合
int _value = 0;
increment() {
_value++;
notifyListeners(); // 通知用到Counter数据的,需要更新
}
int get value => _value; // get方法
}
这样我们的store
就创建完了,里面有一个初始化的数据value
为0,有increment
方法来改变value
的值.
3. 如何使用Store
上一步创建好我们所需要共享的数据类后,我们如何去使用呢?这个也有点类似React中的高阶组件,Provide提供了ProviderNode
方法,该方法传入共享数据和包装的Widget,然后会返回一个包装后的Widget,之后这个组件下的所有页面数据就共享了。
3.1 ProviderNode配置
通过查看编辑器的提示,我们可以知道ProviderNode
需要一个Providers providers
和一个Widget child
。
那我们做如下操作
var providers = new Providers(); // 创建一个providers对象
providers..provide(Provider.value(counter)); // 把Store添加到providers中
//main.dart
void main() {
runApp(
ProviderNode(
child: MyApp(),
providers: providers,
)
);
}
class MyApp extends StatelessWidget{...}
4. 页面中展示共享数据
我们将数据包装给顶级的Widget,所有的页面数据都会共享这个数据。
4.1 在页面中如何展示共享数据呢?
用Provide()构造函数获取到的对应Store数据,代码如下
Widget build(BuildContext context) {
return Container(
child: Provide( // 获取对应Store数据状态
builder: (BuildContext context, Widget child, Counter counter){
return Text(
'${counter.value}', // counter实例
style: TextStyle(fontSize: 30.0),
);
},
),
)
}
4.2 其他组件改变数据
// button
class myButton extends StatelessWidget{
return Container(
child: Container(
child: RaisedButton(
onPressed: () {
Provide.value(context).increment(); // 调用Store中实例的方法改变数据
},
child: Text('增加'),
),
),
);
}
最后看下效果
思考
随着我们项目越来越庞大,我们的数据也会越来越多,store数据也越多,我们最好是把store单独拎出来,统一管理
- lib
- store
- allState // 统一在allState中进行管理
- counter
- moreState
- ...
再在store中新增testTitleStore.dart数据
tsetTitleStore主要是在页面跳转时,动态设置页面的title
- store
// allState.dart
import 'package:provide/provide.dart';
import './counter.dart';
import './testUpdateTitle.dart';
Providers provideAll () {
var counter = Counter();
var providers = Providers();
// 第一种方式
// providers..provide(Provider.value(counter))
// ..provide(Provider.value(TestUpdateTitle()));
// 第二种方式
providers.provideAll({ // 参数是一个Map key是Provider的类型,value是provider
Counter: Provider.value(counter),
TestUpdateTitle: Provider.value(TestUpdateTitle()),
});
return providers;
}
main.dart
import './store/allstate.dart';
void main() {
var providers = provideAll();
runApp(
ProviderNode(
child: MyApp(),
providers: providers,
)
);
}
...
点击页面跳转,触发title更新
// 上个页面
onTap: () {
Provide.value(context).updateTitle('各种小练习');
Navigator.of(context).pushNamed('/myInfo');
},
// 下个页面接受数据
appBar: AppBar(
title: Provide(
builder: (BuildContext context, Widget child, TestUpdateTitle title) {
return Text(
'${title.text}'
);
},
),
),
ok我们来看下效果
附上自己画的Provide数据流向图
总结
flutter中数据状态共享很多,选择一个适合自己的就好,本文介绍了Provide的基本用法,两个小栗子,后面可以再照着新增更多的状态就可以了,后面再研究下其他的flutter的状态管理工具。如何本文对你有帮助请给一个小小的赞❤️,如果本文有写的不对不到位的地方,还请各位大佬在评论区指点,康桑密达~