
当我们开始使用Flutter时,我们使用了Flutter的最爱--供应商。通过这个项目,我们看到了所有的好处和问题,对于下一个项目,我们决定使用Riverpod。从那时起,它一直是我们的状态管理的选择。在这个简单的教程中,我们将创建一个简单的riverpod(1.0.4)使用的例子。如果你读过我以前的文章,你知道我欠你关于快速部署的新东西,但从那时起,我们的Flutter学院占用了我的时间,把我的注意力转移到这个上面,以帮助所有的学生。
步骤1.- 新项目和模拟数据
创建一个新的项目,并在根目录下添加一个数据文件夹(在这个例子中我们将使用json文件,但在这个实现之后,你可以很容易地将其切换为http调用或firestore)。你可以从这个链接中使用json,我们将在项目中使用。
为了使用和访问数据文件夹作为资产,你需要更新你的pubspec.yaml文件。
第二步。- 创建模型类
在lib目录下创建models文件夹,在那里我们将添加movie.dart文件,这将是我们的电影模型类。Flutter架构中的模型对应于MVC。当我们有相同类型的数据,我们期望收到的数据,通过一个模型来处理要容易得多(即使是意外的事情),因为它简化了工作。我们总是知道我们会得到什么,以何种形式得到,这将有助于我们通过应用来管理它。
- 做到这一点的基本方法是定义一个类,并添加所有我们期待的变量,以及构造函数(在我们的案例中,今天也有标准的API格式),从JSON解析模型,也可以解析到JSON。
- 在Json to dart应用程序的帮助下,如果我们有指定的JSON格式,它将为我们做所有的工作,所以不再多说,从movies.json列表中取一个JSON对象,并复制粘贴到json to dart应用程序。正如你所看到的,它甚至为我们处理了JSON对象中的数组数据(唯一的缺点是,它可能不是最新的dart版本,所以你可能需要调整代码,删除例如不必要的关键字等)。
步骤3.- 创建简单的视图
用部件创建一个简单的电影列表。我们提取了一个电影卡小部件,并添加了一个简单的列表视图构建器和一个电影类模型的例子。我们应该有这样的东西。这一步的代码在一个单独的分支中,所以你可以看到它。
第4步。- 引入Flutter Riverpod
首先,我们需要添加一个flutter riverpod包 ,你有一个安装指导,在给定的链接,然后做以下工作。
- 一旦Riverpod安装完毕,我们就可以用一个ProviderScope来包装我们的根部件了。
- ProviderScope是一个小部件,用于存储我们创建的所有提供者的状态。
之后,我们将把我们的StatelessWidget转换成Consumer widget。通过子类化ConsumerWidget,我们的widget的build()方法现在有一个额外的WidgetRef参数,我们可以用它来观察我们的提供者。
什么是WidgetRef?
Riverpod文档将WidgetRef定义为一个允许widget与提供者互动的对象。
为了更好地理解WidgetRef的目的是什么,让我们把它与BuildContext进行比较。
BuildContext让我们访问widget树上的祖先widget(比如Theme.of(context)和MediaQuery.of(context))。
换句话说,WidgetRef让我们访问任何我们想要的提供者。这是设计好的,因为所有的Riverpod提供者都是全局的。
正如我们将看到的,这有很多优点,让我们很容易地将任何状态管理逻辑移到widget树之外。状态可用性的例子。
好了,这个设置仍然与引入riverpod之前的工作方式相同,所以让我们创建我们的第一个提供者。
第5步。- 创建一个电影提供者
Provider和StateProvider对于简单的用例来说已经足够了,比如计数器的例子。但是在更复杂的应用程序中,我们经常需要在widget类之外存储一些状态和一些业务逻辑。
正因为如此,我们将为我们的业务逻辑使用StateNotifier Provider。
StateNotifierProvider是一个用于监听和公开StateNotifier(来自包state_notifier,Riverpod重新出口)的提供者。
StateNotifierProvider和StateNotifier是Riverpod推荐的解决方案,用于管理可能因用户交互而改变的状态。
所以我们需要一个不可变的状态,为了创建这个简单的方法,我们将使用一个叫做freezed的包。它所做的是为我们生成所有的模板代码,所以我们的提供者将是漂亮和干净的。
第一个简单的提供者将加载我们的json电影数据,看起来像这样(如果你只是复制粘贴,不要害怕丢失文件,要创建丢失的freezed文件,你需要运行freezed包说明中的一些命令)。
我们现在也可以清理我们的main.dart文件,只需读取提供者,从列表中看到我们的电影。
第6步。- 添加简单的互动性
我们将添加一个简单的文本输入部件和onChanged函数触发器,我们将从提供者那里调用一个新的方法,称为filterMovies。
所以我们的main.dart现在看起来会是这样。
而出来的movie_provider.dart则是这样。
正如我们所看到的,虽然它是有效的,但我们有太多的重复代码,而且在搜索时没有加载器,当它是一个API请求时,会花费一些时间。
解决问题1:提取加载JSON的服务(以后可以很容易地在一个地方切换到http方法)。
并在提供者中取代获取。现在我们可以在一个地方轻松切换任何类型的数据获取方法。有了资源库(下一篇文章),它将很容易被测试。
解决问题2:在搜索中添加加载器
虽然这个问题可以用FutureProvider自然解决,但我们还是要用最简单的方法来解决这个问题。
- 在MovieState中添加isLoading变量(每次加载都会触发)。
- 运行命令来重新生成电影状态
flutter packages pub run build_runner build - delete-conflicting-outputs
- 并在主屏幕上观察isLoading的情况
给服务添加延迟,以模拟加载器。
也许这不是最理想的方法或代码,但我认为它对初学者是友好的,你可以在这个基础上建立,这是本文的目的。
完整的代码Repo可在github链接中找到。
为什么是Riverpod?
正如文档中所说,为了理解为什么我们需要Riverpod,让我们看看Riverpod解决了Provider的一些最常见的问题。
根据设计,Provider是对InheritedWidget的改进,它依赖于widget树
- 组合Provider是非常冗长的
- 按类型和运行时异常获取Providers
先进的Riverpod功能,我们将在未来谈论更多。
- 自动处置修改器
- 家族修改器
- 使用Riverpod的依赖性重写
- 用Riverpod组合提供程序
- 提供者的范围
我个人认为,对于一个使用redux/vuex等网络背景的人来说,Riverpod是一种非常自然和合理的状态管理方式。Riverpod是一种非常自然和合理的状态管理方式,而且它的核心毕竟是Provider(Flutter的最爱),它是由同一个人做的。在这个简单的项目中,我们没有使用存储库,所以请记住这一点,在我写一篇扩展文章之前,请查看该模式的可测试性。
Flutter Riverpod的简单例子和指南最初发表在Dev Genius的Medium上,在那里人们通过强调和回应这个故事继续对话。