资料
Flutter状态管理:Provider4 SelectorFlutter使用Provider之Cosumer和SelectorFlutter Provider状态管理 - Selector
最简单的使用
上代码
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.orange,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class Counter extends ChangeNotifier {
// 这里也可以使用with来进行实现
int _count = 0; //数值计算
int get count => _count;
addCount() {
_count++;
notifyListeners();
}
}
Counter _counter = Counter();
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
_counter.addListener(() {
// 数值改变的监听
print('YM--->新数值:${_counter.count}');
});
}
@override
void dispose() {
super.dispose();
_counter.dispose(); //移除监听
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Hello')),
body: Center(
child: Container(
child: RaisedButton(onPressed: () {
_counter.addCount();
}, child: Text('计数'),),
),
),
);
}
}
创建一个继承ChangeNotifier的类
class Counter extends ChangeNotifier {
// 这里也可以使用with来进行实现
int _count = 0; //数值计算
int get count => _count;
addCount() {
_count++;
notifyListeners();
}
}
在外边创建一个持久化的对象
Counter _counter = Counter();
在initState的时候注册Listener
@override
void initState() {
super.initState();
_counter.addListener(() {
// 数值改变的监听
print('YM--->新数值:${_counter.count}');
});
}
dispose的时候dispose掉,然后就不能用了
@override
void dispose() {
super.dispose();
_counter.dispose(); //移除监听,再调用的话会崩溃
}
调用_counter.addCount();
_counter.addCount(); // 里面调用了notifyListeners()方法
第二个例子 ChangeNotifierProvider
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart';
class TestProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
int _number = 0;
int get number => _number;
set number(int value) {
_number = value;
notifyListeners();
}
void addNumber() {
_number++;
notifyListeners();
}
}
class UserModel {
String name;
String userID;
bool isAuthor;
bool isVIP;
UserModel(this.name, this.userID, this.isAuthor, this.isVIP);
}
class UserProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
UserModel _user;
UserProviderModel(this._user);
set user(UserModel value) {
_user = value;
notifyListeners();
}
}
void main() {
List<SingleChildWidget> providerList = [
ChangeNotifierProvider(create: (_) => TestProviderModel()),
ChangeNotifierProvider(
create: (_) => UserProviderModel(UserModel("cy", "1", true, true)),
)
];
runApp(
MultiProvider(
providers: providerList,
child: TestProvider(),
),
);
}
class TestProvider extends StatefulWidget {
@override
State<StatefulWidget> createState() => _TestProviderState();
}
class _TestProviderState extends State<TestProvider> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('测试provider')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ChildOne(),
ChildTwo(),
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
context.read<TestProviderModel>().addNumber();
},
),
),
);
}
}
class ChildOne extends StatefulWidget {
@override
State<StatefulWidget> createState() => _ChildOneState();
}
class ChildTwo extends StatefulWidget {
@override
State<StatefulWidget> createState() => _ChildTwoState();
}
class _ChildOneState extends State<ChildOne> {
@override
Widget build(BuildContext context) {
print('1build');
return Container(
child: Text('1number = ${context.watch<TestProviderModel>()._number}'),
);
}
}
class _ChildTwoState extends State<ChildTwo> {
@override
Widget build(BuildContext context) {
print('2build');
return Container(
child: Consumer2<TestProviderModel, UserProviderModel>(
builder: (context, testProvider, userProvider, child) {
return Text(
'testProviderNumber:${testProvider.number}\n用户:${userProvider._user.name}');
},
),
);
}
}
例子 CartModel
import 'dart:collection';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.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();
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Welcome to Flutter",
home: Scaffold(
appBar: AppBar(title: Text('Hello')),
body: ProviderRoute(),
),
);
}
}
class ProviderRoute extends StatefulWidget {
@override
State<StatefulWidget> createState() => _PreviderRouteState();
}
// 这是一个便捷类,会获得当前context和指定数据类型的Provider
class _Consumer<T> extends StatelessWidget {
final Widget Function(BuildContext context, T? value) builder;
const _Consumer({Key? key,required this.builder}) : super(key: key);
@override
Widget build(BuildContext context) {
return builder(
context, context.watch<T>()
);
}
}
class _PreviderRouteState extends State<ProviderRoute> {
@override
Widget build(BuildContext context) => Center(
child: ChangeNotifierProvider<CartModel>(
create: (_) => CartModel(),
child: Builder(
builder: (context) {
return Column(
children: [
Text('Hi~'),
// 下面可以做如下优化
// 1. 需要显示调用ChangeNotifierProvider.of,
// 当APP内部依赖CartModel很多时,这样的代码将会很冗余
// 2. 语义不明确:由于ChangeNotifierProvider是订阅者,那么依赖CartModel
// 的Widget自然就是订阅者,其实也就是状态的消费者,如果我们用Builder
// 来构建,语义就不是很明确;如果我们能使用一个具有明确意义的Widget,比如就叫Consumer
// ,这样最终的代码语义将会很明确,只要看到使用Consumer,我们就知道它是依赖某个跨组件或全局的状态。
// Builder(builder: (context) {
// var cart = context.watch<CartModel>();
// return Text("Hello cart => ${cart.totalPrice}");
// }),
_Consumer<CartModel>(
builder: (context, cart) => Text("总价:${cart?.totalPrice}"),
),
Builder(builder: (context) {
print('ElevatedButton build');
return ElevatedButton(
onPressed: () {
// 给购物车中添加商品,添加后总价会更新
Provider.of<CartModel>(context, listen: false)
.add(Item(20.0, 1));
},
child: Text("添加商品"),
);
}),
],
);
},
),
),
);
}
1. 首先定义一个ChangeNotifier的子类
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();
}
}
2. 监听(弄一个工具类)
// 这是一个便捷类,会获得当前context和指定数据类型的Provider
class _Consumer<T> extends StatelessWidget {
final Widget Function(BuildContext context, T? value) builder;
const _Consumer({Key? key,required this.builder}) : super(key: key);
@override
Widget build(BuildContext context) {
return builder(
context, context.watch<T>()
);
}
}
3. 发送修改事件
Provider.of<CartModel>(context, listen: false).add(Item(20.0, 1));
Selector
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
// 得到的结果, 改成了Selector的形式
// I/flutter (15906): Button 1 被点击了......
// I/flutter (15906): Selector Text 1 重绘了。。。。。。
// I/flutter (15906): Button 2 被点击了.....
// I/flutter (15906): Selector Text 2 重绘了。。。。。。
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.orange,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyPage(),
);
}
}
class CounterProvider with ChangeNotifier {
int _count = 0;
int _count1 = 100;
int get value => _count;
int get value1 => _count1;
void increment() {
_count++;
notifyListeners();
}
void increment1() {
_count1++;
notifyListeners();
}
}
class MyPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return MyPageState();
}
}
class MyPageState extends State<MyPage> {
// 初始化CounterProvider
CounterProvider _counterProvider = new CounterProvider();
@override
Widget build(BuildContext context) {
print('页面重绘了.........');
// 整个页面使用ChangeNotifier来包裹
return ChangeNotifierProvider(
create: (context) => _counterProvider,
// child里面的内容不会因为数据的改变而重绘
child: Scaffold(
appBar: AppBar(title: Text('my page')),
body: Center(
// 使用Consumer来获取provider
child: Column(
children: [
// 使用Selector
Selector(
builder: (BuildContext context, int data, Widget? child) {
print('Selector Text 1 重绘了。。。。。。');
return Text(
'Text1 : ${data.toString()}',
style: TextStyle(fontSize: 20),
);
},
selector: (
BuildContext context,
CounterProvider counterProvider,
) {
return counterProvider.value;
},
),
Selector(
builder: (BuildContext context, int data, Widget? child) {
print('Selector Text 2 重绘了。。。。。。');
return Text(
'Text2 : ${data.toString()}',
style: TextStyle(fontSize: 20),
);
},
selector: (
BuildContext context,
CounterProvider counterProvider,
) {
return counterProvider.value1;
},
),
RaisedButton(
onPressed: () {
print('Button 1 被点击了......');
_counterProvider.increment();
},
child: Text('Button1'),
),
RaisedButton(
onPressed: () {
print('Button 2 被点击了.....');
_counterProvider.increment1();
},
child: Text('Button2'),
),
],
),
),
),
);
}
}