Flutter 状态管理 Provider 快速指南【Flutter 专题 8】
Flutter 状态管理 Provider 快速指南
前面给大家讲了 http,dio,已经可以和后端交互了,还讲了动画等知识也可以做简单的界面了接下来就和大家一起了解状态管理
状态管理的概念仍然是 Flutter 中最关键的主题之一。这是因为我们在 Flutter 中所做的一切,从与接收用户信息相关的操作到显示一条数据,都与状态有关。因此,以尽可能最好的方式管理这些数据可确保应用程序编码清晰、抽象正确、运行顺畅并尽可能提供最佳结果。
现在已经开发了许多状态管理解决方案,每个解决方案都基于以最干净和最容易访问的方式操作或修改状态的相同概念。在本文中,我们将构建一个示例应用程序,其中包含 Flutter 的最佳状态管理包之一:Provider。
在开始之前,请注意,本文假设您的机器上有一个可操作的 Flutter 开发环境,以及 Flutter 的工作知识。
让我们来谈谈在 Flutter 应用程序中管理状态意味着什么。
Flutter 中的状态是什么?
Flutter 中的“状态”是指存储在小部件中的数据,可以根据当前操作进行修改。应用程序的状态可以在应用程序启动时或重新加载页面时更新或完全更改。
这意味着小部件所做的一切都需要处理从用户那里检索到的数据并在它们之间传递数据以执行一个或多个操作。Flutter 还可以使用状态向用户显示信息片段。
什么是 Provider?
Provider 包是由 Remi Rousselet 创建旨在尽可能快速地处理状态。在 Provider 中,小部件会监听状态的变化,并在收到通知后立即更新。
因此,当有状态改变时,而不是重建整个 widget 树,只改变受影响的 widget,从而减少工作量并使应用程序运行得更快更流畅。
使用 Provider 进行状态管理
回想一下我们之前讨论过的关于 Provider 的内容:小部件侦听更改并在重建时相互通知。一旦状态发生变化,该特定小部件就会重建,而不会影响小部件树中的其他小部件。
Provider 中的三个主要组件使这一切成为可能:ChangeNotifier
Flutter 中的类、ChangeNotifierProvider
(主要用于我们的示例应用程序)和Consumer
小部件。
Provider 的三个好兄弟:
老大 -- MultiProvider(供货商)
作用:
包裹根节点,将我们准备好的 Model 和 View 建立联系;可以想象成一只巨大章鱼包裹了一棵大树,他可以将触手随意的伸向某一节树枝;
老二 -- Providers(货源)
作用:
负责预先定义好,需要被共享的 Model;
大儿子:provider 不需要被监听,有的常量或者方法,根本不需要“牵一发而动全身”,也就是说他们不会被要求随着变动而变动,这样的需求就用大儿子定义;
二儿子: ChangeNotifierProvider 对这个儿子父亲要求的就比较多了,它会随着某些数据改变而被通知更新,也就是说,比如这个 Model 被用在多个 page,那么当其中一处被改变时,他就应该告诉其他的地方,改更新了,这样的需求就是用二儿子定义;
三儿子: ChangeNotifierProxyProvider 对这个儿子要求就更高了,所以它的名字都比老二长一截,他不仅要像老二一样,通知更新,还要协调 Model 与 Model 之间的更新,比如一个 ModelA 依赖另一个 ModelB,ModelB 更新,他就要让依赖它的 ModelA 也随之更新,这就是老三的活;
老三 -- Provider.of<T>(context) / Widget Consumer(消费者)
作用:负责从各个节点取出数据来使用的
从ChangeNotifier
类中观察到的任何状态变化都会导致监听小部件重建。Provider 包提供了不同类型的 Provider——下面列出了其中的一些:
Provider
类取值并暴露,而不管值类型的ListenableProvider
是用于可听对象的特定提供程序。它将侦听,然后根据它询问小部件并受状态更改的影响以在调用侦听器时重建ChangeNotifierProvider
类似于ListenableProvider
但对于ChangeNotifier
对象,并在需要时自动调用ChangeNotifier.dispose
ValueListenableProvider
侦听 aValueListenable
并公开值StreamProvider
侦听流,公开最新发出的值,并要求依赖于流的小部件重建FutureProvider
接受一个Future
类并在未来完成时根据它更新小部件
入门
首先创建一个新项目并将此行添加到pubspec.yaml
文件中的依赖项块:
运行命令以获取包的本地副本:pub get
接下来,我们需要在main.dart
文件中创建一个新的 Material 应用程序:
管理状态数据
现在,创建一个包含应用程序所需状态数据的新类。让我们命名它UserDetailsProvider
。该UserDetailsProvider
类将处理所有涉及此处理状态的方法。
这个类扩展了ChangeNotifier
类;ChangeNotifier
为我们提供对notifyListeners
方法的访问,我们将使用该方法通知监听小部件在状态更改时重建。
我们为TextFormField
:name
和声明了两个控制器age
。该类中还声明了根据用户输入更新用户姓名和年龄的方法。
处理应用程序状态的所有内容都在此处声明:
更新状态
名称更新后,我们调用该notifyListeners
方法,该方法将状态更改通知侦听小部件,从而触发所有相关小部件的重建。
现在我们有了UserDetailsProvider
类(处理状态),我们需要使用ChangeNotifierProvider
. 现在,在主块ChangeNotifierProvider
的runApp
方法中使用 a 包装整个应用程序。
该ChangeNotifierProvider
暴露了两个重要的特性:create
和child
。我们声明的类 extends ChangeNotifier
,被传递到create
属性中,将类链接到页面:
现在应用程序链接到提供状态的类;每当状态发生变化时,都会导致应用程序内页面的重建。
收集用户数据
目前,HomeScreen
小部件包含一个带有两个TextFormField
s 的表单,用于接收用户的姓名和年龄。此外,RawMaterialButton
还包含 在用户传递所需的详细信息后保存更改。
在这组小部件之后,我们有两个Text
小部件显示用户给出的值。这两个小部件是唯一需要在应用程序状态发生变化时更新的小部件。
这意味着我们不需要在每次状态发生变化时重建每个屏幕。因此,我们需要一种方法来选择性地仅重建Text
与状态变化有关的小部件。为此,我们有Consumer
小部件。
有选择地更新状态
该Consumer
控件只允许子控件,而不在 widget 树影响其他部件重建。如前所述,我们只希望text
显示用户提供的详细信息的小部件进行更新。
我们通过Text
用 a 包装两个小部件Column
并builder
在Consumer
小部件公开的函数处返回它来实现这一点:
现在,Text
每当应用程序中的状态发生变化时,只有小部件会更新。
确保尽可能使用最低级别的提供程序;您只能将提供程序用于受影响的小部件。在高级别使用它会导致不关心状态更改的小部件重建。与Consumer
小部件相同的事情;确保您在特定级别使用以避免重建整个小部件树。
我们的示例应用程序终于准备好了!
结论
强调 Flutter 中状态管理的重要性怎么强调都不为过。今天,我们剖析了 Provider 包并使用它来管理示例 Flutter 应用程序的状态。希望通过在本文构建应用程序所获得的实践知识,您现在可以以一种干净,快速且更易于访问的方式正确管理应用程序的状态。
版权声明: 本文为 InfoQ 作者【坚果前端】的原创文章。
原文链接:【http://xie.infoq.cn/article/08bf90c329722ab348352d019】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论