直接开始干,没有为何~html
上一篇看了官方的默认的计数 Demo ,在 2019 Google I/O 大会中, Provider 代替 Provide 成为官方推荐的状态管理方式之一。git
Provider 能够干什么?引用官方的一段话:github
By using widgets for state management, provider can guarantee:app
maintainability, through a forced uni-directional data-flow testability/composability, since it is always possible to mock/override a value robustness, as it is harder to forget to handle the update scenario of a model/widgetless
我的总结:提升项目可维护性,使结构更加清晰,重要的是提供单向数据流,实现更小单元的刷新,提高性能。ide
接下来就用 Provider 改造下默认的技术Demo。性能
在 pubspec.yaml 中增长 provider: ^3.1.0 ,而后点击 右上角 Packages get 就能够了,这里说明下:字体
^ 表示适配和当前大版本一致的版本,~ 表示适配和当前小版本一致的版本,因此这里的 ^ 能够不要。ui
dependencies:
flutter:
sdk: flutter
...
# Provider https://github.com/rrousselGit/provider
provider: ^3.1.0
复制代码
import 'package:flutter/foundation.dart';
class CounterNotifier with ChangeNotifier {
int _count = 0;
int get count => _count;
increment() {
_count++;
notifyListeners();
}
}
复制代码
import 'package:flutter/material.dart';
import 'package:flutter_provider_demo/CounterNotifier.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 建立 Widget 持有 CounterNotifier 数据
return ChangeNotifierProvider.value(
value: CounterNotifier(),
child: MaterialApp(
title: 'Privoder Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ProvidePage(title: 'Provider Demo Home Page'),
),
);
}
}
class ProvidePage extends StatelessWidget {
final String title;
ProvidePage({Key key, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
// 获取 CounterNotifier 数据
final counter = Provider.of<CounterNotifier>(context);
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'${counter.count}',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
counter.increment();
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
复制代码
这样就完成了使用 Provider 对默认计数 Demo 改造,使用 Provider.of 当ChangeNotifier 中调用 notifyListeners 时每次会从新调用 Widget 中的 buildthis
这里实现个稍微复杂点的,建立 Page1 显示 current count,而后建立 Page2 实现官方默认点击计数,看看 Provider 状态管理效果。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// return Provider.value(
// value: 36,
// child: ChangeNotifierProvider.value(
// value: CounterNotifier(),
// child: MaterialApp(
// title: 'Privoder Demo',
// theme: ThemeData(
// primarySwatch: Colors.blue,
// ),
// home: Page1(),
// ),
// ),
// );
return MultiProvider(
providers: [
Provider.value(value: 36),
ChangeNotifierProvider.value(value: CounterNotifier())
],
child: MaterialApp(
title: 'Privoder Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Page1(),
),
);
}
}
复制代码
class Page1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
//获取文字大小
final size = Provider.of<int>(context).toDouble();
// 获取计数
final counter = Provider.of<CounterNotifier>(context);
// 调用 build 时输出
print('rebuild page 1');
return Scaffold(
appBar: AppBar(
title: Text('Page1'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// 显示计数
Text(
'Current count: ${counter.count}',
// 设置文字大小
style: TextStyle(
fontSize: size,
),
),
SizedBox(
height: 50,
),
// 跳转 Page2
RaisedButton(
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(builder: (context) => Page2()),
),
child: Text('Next'),
),
],
),
),
);
}
}
复制代码
class Page2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('rebuild page 2');
return Scaffold(
appBar: AppBar(
title: Text('Page2'),
),
body: Center(
child: Consumer2<CounterNotifier, int>(
builder: (context, counter, size, _) {
print('rebuild page 2 refresh count');
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'${counter.count}',
style: TextStyle(
fontSize: size.toDouble(),
),
),
],
);
}),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// 不须要监听改变(listen: false 不会从新调用build)
Provider.of<CounterNotifier>(context, listen: false).increment();
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
复制代码
2019-09-14 22:21:31.393 14373-14467/com.joker.flutter_provider_demo I/flutter: rebuild page 1 2019-09-14 22:21:31.406 14373-14467/com.joker.flutter_provider_demo I/flutter: rebuild page 2 refresh count
经过这个日志能够看出,使用 Consumer 能够实现局部刷新,因此它的性能更优,应该优先选用。可是 Consumer 只有 Consumer ~ Consumer6,没有多的是实现。若是须要则只有本身实现。
一点建议:不要吝啬逗号,这会让你的代码结构看起来更爽
provider 提供了几种不一样类型得 XXProvider ,使用方法都大同小异
name | description |
---|---|
Provider | 最基本得 provider. 携带一个 value 并暴露它. |
ListenableProvider | Listenable 对象的特定 Provider 。ListenableProvider将监听对象,以便在调用侦听器时重建依赖它的 Widgets。 |
ChangeNotifierProvider | 一个具体的 ListenableProvider 监听 ChangeNotifier 。它会在须要时自动调用ChangeNotifier.dispose。 |
ValueListenableProvider | 监听 ValueListenable 并仅暴露 ValueListenable.value。 |
StreamProvider | 监听 Stream 并暴露最新发出的值。 |
FutureProvider | 携带一个 Future,并在 Future 完成时更新依赖 |
以上就是 Provider 使用,最后奉上Demo地址