区块链技术博客
www.b2bchain.cn

Flutter 状态管理之 Provider求职学习资料

本文介绍了Flutter 状态管理之 Provider求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

为什么需要状态管理

如果我们的应用足够简单,Flutter 作为一个声明式框架,你或许只需要将数据映射成视图就可以了,你可能并不需要状态管理,就像下面这样。

Flutter 状态管理之 Provider

但是随着功能的增加,你的应用程序将会有几十个甚至上百个状态,这个时候你的应用应该会是这样

Flutter 状态管理之 Provider

随着你的应用需要共享多处统一状态时,我们很难再清楚的测试维护我们的状态,因为它看上去实在是太复杂了!而且还会有多个页面共享同一个状态,例如当你进入一个文章点赞,退出到外部缩略展示的时候,外部也需要显示点赞数,这时候就需要同步这两个状态。

Flutter 实际上在一开始就为我们提供了一种状态管理方式 — StatefulWidget。然而我们发现它仅适合用于在单个 Widget 内部维护其状态。当我们需要使用跨组件的状态时,StatefulWidget 将不再是一个好的选择。

State 属于某一个特定的 StatefulWidget,在多个 Widget 之间进行交流的时候,虽然你可以使用 callback 解决,但是当嵌套足够深的话,很容易就增大代码耦合度。

这时候,我们便迫切的需要一个架构来帮助我们理清这些关系,状态管理框架应运而生。

什么是 Provider

那么我们该如何解决上面这种糟糕的情况呢。在上手了 Provider 之后,这个库是一个相当不错的解决方案,我们先来简单说一下 Provider 的基本作用。

Provider 从名字上就很容易理解,它用来提供数据,而它的优秀之处在于无论是在单个页面还是在整个 app 都有相应的解决方案,我们可以很方便的管理状态,并在合适的时机释放资源,可以说,Provider 的目标就是完全替代 StatefulWidget。

Flutter 状态管理之 Provider

创建一个简单计数器 App

这里我们用这个 Counter App 为例,给大家介绍如何在两个独立的页面中共享计数器(counter)的状态应该怎么做,具体会像下面这样。

Flutter 状态管理之 Provider

  • 两个页面中心字体共用了同一个字体大小。
  • 第二个页面的按钮将会让数字增加(第一个页面的数字将会同步增加。)

1. 添加依赖

在 pubspec.yaml 中添加 Provider 的依赖。

dependencies:   provider: ^5.0.0
  • 实际添加请参考:https://pub.flutter-io.cn/packages/provider

2. 创建数据 Model

class CounterModel with ChangeNotifier {   int _count = 0;    int get count => _count;    void increment() {     _count++;     notifyListeners(); // 当数值改变后,通知所有订阅者   } }
  • Model 需要 mixin 混入 ChangeNotifier,当调用 notifyListeners() ,它会通知所有订阅者。

3. 创建顶层共享数据

void main() {   final counter = CounterModel();   final textSize = 48;    runApp(MultiProvider(     providers: [       ChangeNotifierProvider<CounterModel>(create: (_) {         return CounterModel();       }),       Provider<int>.value(value: textSize),     ],     child: MyApp(),   )); }  class MyApp extends StatelessWidget {   @override   Widget build(BuildContext context) {     return MaterialApp(       theme: ThemeData.dark(),       home: FirstPage(),     );   } }
  • MultiProvider 继承于 Nested,可以支持传入多个 Provider,根据官方文档介绍或者查看源码,其实 Provider 是基于 InheritedWidget 封装的。
  • ChangeNotifierProvider<T> 能够提供数据供子孙节点使用,还可以通过 notifyListeners 通知所有听众刷新。
  • Provider<T>.value 能够管理一个恒定的数据,并提供给子孙节点使用。我们只需要将数据在其 value 属性中声明即可。在这里我们将textSize 传入,它提供了 typedef UpdateShouldNotify<T> = bool Function(T previous, T current); 的方法用于控制刷新时机,我们可以在这里传入一个方法 (T previous, T current){...},并获得前后两个 Model 的实例,然后通过比较两个 Model 以自定义刷新规则,这个方法将返回 bool 表示是听众否需要刷新。(默认为 previous != current 则刷新。)

4. 获取状态

4.1 全量重建 widget

App 有 FirstPage、SecondPage 两个页面,先看下 FirstPage 页面:

class FirstPage extends StatelessWidget {   @override   Widget build(BuildContext context) {     final counter = Provider.of<CounterModel>(context);     final textSize = Provider.of<int>(context).toDouble();      return Scaffold(       appBar: AppBar(         title: Text('FirstPage'),       ),       body: Center(         child: Text(           'Value: ${counter.count}',           style: TextStyle(fontSize: textSize),         ),       ),       floatingActionButton: FloatingActionButton(         onPressed: () => Navigator.of(context)             .push(MaterialPageRoute(builder: (context) => SecondPage())),         child: Icon(Icons.navigate_next),       ),     );   } }
  • 获取并监听顶层数据最简单的方法就是 Provider.of<T>(context); 它会监听数据的改变而重新调用 build() 从而做到状态更新,它后面还有个 bool 类型的可选参数 listen,默认为 true,相当于 context.watch<T>();,当设置为 false 则不会有监听数据的改变而刷新的能力,一般用于初始化,相当于 context.read<T>();

4.2 局部重建 widget

考虑到 build 整个 widget 的代价比较大,那么 Provider 是否有控制局部刷新的能力呢?答案是肯定有的,一起来看下 SecondPage 页面:

“`dart
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(

为什么需要状态管理

如果我们的应用足够简单,Flutter 作为一个声明式框架,你或许只需要将数据映射成视图就可以了,你可能并不需要状态管理,就像下面这样。

Flutter 状态管理之 Provider

但是随着功能的增加,你的应用程序将会有几十个甚至上百个状态,这个时候你的应用应该会是这样

Flutter 状态管理之 Provider

随着你的应用需要共享多处统一状态时,我们很难再清楚的测试维护我们的状态,因为它看上去实在是太复杂了!而且还会有多个页面共享同一个状态,例如当你进入一个文章点赞,退出到外部缩略展示的时候,外部也需要显示点赞数,这时候就需要同步这两个状态。

Flutter 实际上在一开始就为我们提供了一种状态管理方式 — StatefulWidget。然而我们发现它仅适合用于在单个 Widget 内部维护其状态。当我们需要使用跨组件的状态时,StatefulWidget 将不再是一个好的选择。

State 属于某一个特定的 StatefulWidget,在多个 Widget 之间进行交流的时候,虽然你可以使用 callback 解决,但是当嵌套足够深的话,很容易就增大代码耦合度。

这时候,我们便迫切的需要一个架构来帮助我们理清这些关系,状态管理框架应运而生。

什么是 Provider

那么我们该如何解决上面这种糟糕的情况呢。在上手了 Provider 之后,这个库是一个相当不错的解决方案,我们先来简单说一下 Provider 的基本作用。

Provider 从名字上就很容易理解,它用来提供数据,而它的优秀之处在于无论是在单个页面还是在整个 app 都有相应的解决方案,我们可以很方便的管理状态,并在合适的时机释放资源,可以说,Provider 的目标就是完全替代 StatefulWidget。

Flutter 状态管理之 Provider

创建一个简单计数器 App

这里我们用这个 Counter App 为例,给大家介绍如何在两个独立的页面中共享计数器(counter)的状态应该怎么做,具体会像下面这样。

Flutter 状态管理之 Provider

  • 两个页面中心字体共用了同一个字体大小。
  • 第二个页面的按钮将会让数字增加(第一个页面的数字将会同步增加。)

1. 添加依赖

在 pubspec.yaml 中添加 Provider 的依赖。

dependencies:   provider: ^5.0.0
  • 实际添加请参考:https://pub.flutter-io.cn/packages/provider

2. 创建数据 Model

class CounterModel with ChangeNotifier {   int _count = 0;    int get count => _count;    void increment() {     _count++;     notifyListeners(); // 当数值改变后,通知所有订阅者   } }
  • Model 需要 mixin 混入 ChangeNotifier,当调用 notifyListeners() ,它会通知所有订阅者。

3. 创建顶层共享数据

void main() {   final counter = CounterModel();   final textSize = 48;    runApp(MultiProvider(     providers: [       ChangeNotifierProvider<CounterModel>(create: (_) {         return CounterModel();       }),       Provider<int>.value(value: textSize),     ],     child: MyApp(),   )); }  class MyApp extends StatelessWidget {   @override   Widget build(BuildContext context) {     return MaterialApp(       theme: ThemeData.dark(),       home: FirstPage(),     );   } }
  • MultiProvider 继承于 Nested,可以支持传入多个 Provider,根据官方文档介绍或者查看源码,其实 Provider 是基于 InheritedWidget 封装的。
  • ChangeNotifierProvider<T> 能够提供数据供子孙节点使用,还可以通过 notifyListeners 通知所有听众刷新。
  • Provider<T>.value 能够管理一个恒定的数据,并提供给子孙节点使用。我们只需要将数据在其 value 属性中声明即可。在这里我们将textSize 传入,它提供了 typedef UpdateShouldNotify<T> = bool Function(T previous, T current); 的方法用于控制刷新时机,我们可以在这里传入一个方法 (T previous, T current){...},并获得前后两个 Model 的实例,然后通过比较两个 Model 以自定义刷新规则,这个方法将返回 bool 表示是听众否需要刷新。(默认为 previous != current 则刷新。)

4. 获取状态

4.1 全量重建 widget

App 有 FirstPage、SecondPage 两个页面,先看下 FirstPage 页面:

class FirstPage extends StatelessWidget {   @override   Widget build(BuildContext context) {     final counter = Provider.of<CounterModel>(context);     final textSize = Provider.of<int>(context).toDouble();      return Scaffold(       appBar: AppBar(         title: Text('FirstPage'),       ),       body: Center(         child: Text(           'Value: ${counter.count}',           style: TextStyle(fontSize: textSize),         ),       ),       floatingActionButton: FloatingActionButton(         onPressed: () => Navigator.of(context)             .push(MaterialPageRoute(builder: (context) => SecondPage())),         child: Icon(Icons.navigate_next),       ),     );   } }
  • 获取并监听顶层数据最简单的方法就是 Provider.of<T>(context); 它会监听数据的改变而重新调用 build() 从而做到状态更新,它后面还有个 bool 类型的可选参数 listen,默认为 true,相当于 context.watch<T>();,当设置为 false 则不会有监听数据的改变而刷新的能力,一般用于初始化,相当于 context.read<T>();

4.2 局部重建 widget

考虑到 build 整个 widget 的代价比较大,那么 Provider 是否有控制局部刷新的能力呢?答案是肯定有的,一起来看下 SecondPage 页面:

“`dart
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(

为什么需要状态管理

如果我们的应用足够简单,Flutter 作为一个声明式框架,你或许只需要将数据映射成视图就可以了,你可能并不需要状态管理,就像下面这样。

Flutter 状态管理之 Provider

但是随着功能的增加,你的应用程序将会有几十个甚至上百个状态,这个时候你的应用应该会是这样

Flutter 状态管理之 Provider

随着你的应用需要共享多处统一状态时,我们很难再清楚的测试维护我们的状态,因为它看上去实在是太复杂了!而且还会有多个页面共享同一个状态,例如当你进入一个文章点赞,退出到外部缩略展示的时候,外部也需要显示点赞数,这时候就需要同步这两个状态。

Flutter 实际上在一开始就为我们提供了一种状态管理方式 — StatefulWidget。然而我们发现它仅适合用于在单个 Widget 内部维护其状态。当我们需要使用跨组件的状态时,StatefulWidget 将不再是一个好的选择。

State 属于某一个特定的 StatefulWidget,在多个 Widget 之间进行交流的时候,虽然你可以使用 callback 解决,但是当嵌套足够深的话,很容易就增大代码耦合度。

这时候,我们便迫切的需要一个架构来帮助我们理清这些关系,状态管理框架应运而生。

什么是 Provider

那么我们该如何解决上面这种糟糕的情况呢。在上手了 Provider 之后,这个库是一个相当不错的解决方案,我们先来简单说一下 Provider 的基本作用。

Provider 从名字上就很容易理解,它用来提供数据,而它的优秀之处在于无论是在单个页面还是在整个 app 都有相应的解决方案,我们可以很方便的管理状态,并在合适的时机释放资源,可以说,Provider 的目标就是完全替代 StatefulWidget。

Flutter 状态管理之 Provider

创建一个简单计数器 App

这里我们用这个 Counter App 为例,给大家介绍如何在两个独立的页面中共享计数器(counter)的状态应该怎么做,具体会像下面这样。

Flutter 状态管理之 Provider

  • 两个页面中心字体共用了同一个字体大小。
  • 第二个页面的按钮将会让数字增加(第一个页面的数字将会同步增加。)

1. 添加依赖

在 pubspec.yaml 中添加 Provider 的依赖。

dependencies:   provider: ^5.0.0
  • 实际添加请参考:https://pub.flutter-io.cn/packages/provider

2. 创建数据 Model

class CounterModel with ChangeNotifier {   int _count = 0;    int get count => _count;    void increment() {     _count++;     notifyListeners(); // 当数值改变后,通知所有订阅者   } }
  • Model 需要 mixin 混入 ChangeNotifier,当调用 notifyListeners() ,它会通知所有订阅者。

3. 创建顶层共享数据

void main() {   final counter = CounterModel();   final textSize = 48;    runApp(MultiProvider(     providers: [       ChangeNotifierProvider<CounterModel>(create: (_) {         return CounterModel();       }),       Provider<int>.value(value: textSize),     ],     child: MyApp(),   )); }  class MyApp extends StatelessWidget {   @override   Widget build(BuildContext context) {     return MaterialApp(       theme: ThemeData.dark(),       home: FirstPage(),     );   } }
  • MultiProvider 继承于 Nested,可以支持传入多个 Provider,根据官方文档介绍或者查看源码,其实 Provider 是基于 InheritedWidget 封装的。
  • ChangeNotifierProvider<T> 能够提供数据供子孙节点使用,还可以通过 notifyListeners 通知所有听众刷新。
  • Provider<T>.value 能够管理一个恒定的数据,并提供给子孙节点使用。我们只需要将数据在其 value 属性中声明即可。在这里我们将textSize 传入,它提供了 typedef UpdateShouldNotify<T> = bool Function(T previous, T current); 的方法用于控制刷新时机,我们可以在这里传入一个方法 (T previous, T current){...},并获得前后两个 Model 的实例,然后通过比较两个 Model 以自定义刷新规则,这个方法将返回 bool 表示是听众否需要刷新。(默认为 previous != current 则刷新。)

4. 获取状态

4.1 全量重建 widget

App 有 FirstPage、SecondPage 两个页面,先看下 FirstPage 页面:

class FirstPage extends StatelessWidget {   @override   Widget build(BuildContext context) {     final counter = Provider.of<CounterModel>(context);     final textSize = Provider.of<int>(context).toDouble();      return Scaffold(       appBar: AppBar(         title: Text('FirstPage'),       ),       body: Center(         child: Text(           'Value: ${counter.count}',           style: TextStyle(fontSize: textSize),         ),       ),       floatingActionButton: FloatingActionButton(         onPressed: () => Navigator.of(context)             .push(MaterialPageRoute(builder: (context) => SecondPage())),         child: Icon(Icons.navigate_next),       ),     );   } }
  • 获取并监听顶层数据最简单的方法就是 Provider.of<T>(context); 它会监听数据的改变而重新调用 build() 从而做到状态更新,它后面还有个 bool 类型的可选参数 listen,默认为 true,相当于 context.watch<T>();,当设置为 false 则不会有监听数据的改变而刷新的能力,一般用于初始化,相当于 context.read<T>();

4.2 局部重建 widget

考虑到 build 整个 widget 的代价比较大,那么 Provider 是否有控制局部刷新的能力呢?答案是肯定有的,一起来看下 SecondPage 页面:

“`dart
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » Flutter 状态管理之 Provider求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们