flutter 状态管理 Provider
2019-07-05 本文已影响0人
贩卖日落的他
本文只简单介绍Provider的用法和使用中遇到的问题
2019 Google I/O 大会上,官方正式介绍了 由社区作者 [Remi Rousselet] 与 Flutter Team 共同编写的 [Provider] 代替 Provide 成为官方推荐的状态管理方式之一。下面以最简单的计数器为例。
1.在pubspec.yaml中引入Provider 包
dependencies:
flutter:
sdk: flutter
provider : ^3.0.0+1
2.新建CouterProvider
import 'package:flutter/material.dart';
class CounterBloc with ChangeNotifier { //混入
int _counter = 0;
int get counter => _counter; //将couter 暴露出去
increment() {
_counter++;
notifyListeners(); // 通知状态改变
}
decrement() {
_counter--;
notifyListeners();
}
}
3.在顶层注入Provider
import 'package:provider/provider.dart';
import './provide/couter.dart';
void main() {
Provider.debugCheckInvalidValueType = null; /*** Provider如果与Listenable/一起使用,现在抛出Stream。考虑使用ListenableProvider/ StreamProvider代替。或者,可以通过设置Provider.debugCheckInvalidValueType 为null这样来禁用此异常***/
runApp(
MultiProvider( //使用MultiProvider可管理多个Provider
providers: [
ChangeNotifierProvider(builder: (_) => HomeProvide()),
],
child: MyApp(),
),
);
}
4.页面获取数据和改变数据
// 方法一 通过Provider.of<CounterBloc>(context) 获取数据方法
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counter =Provider.of<CounterBloc>(context); // 拿到Provider
return Scaffold(
appBar: AppBar(title: Text('provider计数器'),),
floatingActionButton: FloatingActionButton(
onPressed: (){
Provider.of<CounterBloc>(context, listen: false).increment(); /*** 调用增加方法,ChangeNotifierProvider通知依赖重建Widget ,此处特别注意listen:false,如果[listen]为“true”(默认),则以后的值更改将触发小部件的新[state.build]和的[state.didchangeDependencies],,数据将会无限请求***/
},
child: Icon(Icons.add),
),
body: Container(
child: Center(
child: Text('${counter.counter}'),
),
),
);
}
}
// 方法二: 通过Consumer获取数据
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counter =Provider.of<CounterBloc>(context);
return Consumer(
builder: (context,CounterBloc counter,_){
return Scaffold(
appBar: AppBar(title: Text('Provider计数器'),),
floatingActionButton: FloatingActionButton(
onPressed: (){},
child: Icon(Icons.add),
),
body: Container(
child: Center(
child: Text(counter.counter.toString()),
),
),
);
},
);
}
}
4.注意事项
Provider.of<T>(context) 会导致调用的 context 页面范围的刷新。
Consumer 只刷新了 Consumer 的部分
建议尽量使用 Consumer 而不是 Provider.of<T>(context) 获取顶层数据
特别注意尽量保证build 无副作用,不然页面经常重绘
如有不对,请指正