一、为什么需要Provider管理状态
数据变化,数据共享,需要Provider
- Flutter的代码,是响应式/声明式的。以前安卓/iOS的代码,是命令式的。
- 响应式的代码,基本都需要进行状态管理,也可以理解为数据共享。
- 界面、数据是变化的,就需要管理的,简单的直接在StatefulWidget进行管理就好,复杂的就是用Provider之类来管理。
简单和复杂数据的例子:
数据的变化,怎么算简单的呢?——比如一个 PageView 组件中的当前页面、一个复杂动画中当前进度、一个 BottomNavigationBar 中当前被选中的 tab。这些在widget 树,其他部分不需要访问这种状态。不需要去序列化这种状态,这种状态也不会以复杂的方式改变。
什么数据变化需要Privider来管理呢?举例子,比如,用户选项、登录信息、一个社交应用中的通知、一个电商应用中的购物车、一个新闻应用中的文章已读/未读状态。
Flutter的状态管理有Redux、Rx、hooks、ScopedModel, 和Provider等,其中Provider是官方推荐的。
如果你不了解其他的,那肯定是官方推荐的优先。
二、Provider的使用
嗯,Provider是官方推荐的。不熟悉的,可以看看这两篇先。
Provider官方文章
使用 Provider 管理 Flutter 应用状态
1.使用步骤
引入 provider
1 | dependencies: |
关于 provider 的使用可以简单理解为3步:
1.创建继承自 ChangeNotifier 的共享类
2.设置数据
3.获取数据,2种方式,分别是Provider.of(context)
和 Consumer
很简单吧~
2.最简单的例子 Provider.of(context)
方式
以下代码:
- 创建共享类,添加一个增长数据的方法,调用就刷新
- 调用数据
- build重新调用,刷新ui
1 | import 'package:flutter/material.dart'; |
效果:
注意
使用 Provider.of
当ChangeNotifier 中调用 notifyListeners 时每次会重新调用 Widget 中的 build
大概如此了。你可能谁说,直接 setState 就好了。不,这肯定不一样,setState太不灵活了。
3.例子 Consumer 方式
例子:在页面一设置1个值,然后在页面2显示出来 (不要问为什么不直接用Navigator,演示演示,只为演示)
1 | import 'package:flutter/material.dart'; |
注意
1、在Page2中,使用了Consumer
2、Provider.of
的listen如果为false,不会重新调用build
页面2设置数值,返回页面1时,页面1显示的是页面2的数值
对比
- 触发者(
Provider.of
):如果只是需要获取到数据model,不需要监听变化(例如点击按钮),推荐使用Provider.of(context, listen: false)
来获取数据model。 - 监听者(推荐使用Consumer):推荐使用Consumer。
Provider分类
Provider
最基础的Provider,它持有一个类型的值,并暴露出去,并且在任何时候都能获取到最新的值。一般情况下,下层获取上层状态,不过下层是监听不到上层状态的变化。在程序越来越复杂的情况下,使用它在多个Widget中共享状态,还是很方便的。
提示:同种类型,Provider只能维护一份数据。
ListenableProvider
监听状态改变并重绘视图。
ChangeNotifierProvider
与ListenableProvider区别在于,当需要的时候,会自动调用dispose.
ValueListenableProvider
与ListenableProvider区别在于,仅仅支持value方式获取状态。
StreamProvider
以流的方式共享数据。
FutureProvider
持有Future,并在Future完成时,通知监听者。
ProxyProvider 系列
当一个 Model 与其它的Model或者更多的Model之间存在依赖关系,即多个Model状态发生改变,都会引起这个 Model 的状态发生变化,需要使用 ProxyProvider 系列 建立多种Model之间的依赖关系。
ProxyProvider 系列包含:
- ProxyProvider - ProxyProvider6
- ListenableProxyProvider - ListenableProxyProvider6
- ChangeNotifierProxyProvider - ChangeNotifierProxyProvider6
- xxxProxyProvider
这些ProxyProvider的使用基本上同Provider的使用,下文会着重介绍。
使用哪种Provider?
- 需求:多个Widget共享状态,如果没有这个需求,额,怎么会没有呢,好奇怪。
- 当不需要监听状态改变,下层仅仅是获取上层状态,使用
Provider
. - 需要共享数据,并监听数据发生变化,使用
ListenableProvider
或者ChangeNotifierProvider
,如果自主管理数据的dispose,使用ListenableProvider. - 如果两种类型数据,或者多种数据存在依赖关系,使用
ProxyProvider
系列。 - 最方便的使用,也是懒人最强方式,使用
ChangeNotifierProvider
和ChangeNotifierProxyProvider
. - 技术正在不断的完善,官方更新比较频繁,需要时时关注动态。