写点什么

Flutter 状态管理 Provider 快速指南【Flutter 专题 8】

作者:坚果前端
  • 2021 年 11 月 27 日
  • 本文字数:3532 字

    阅读完需:约 12 分钟

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 中的三个主要组件使这一切成为可能:ChangeNotifierFlutter 中的类、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文件中的依赖项块:


dependencies: provider: ^6.0.1
复制代码


运行命令以获取包的本地副本:pub get


flutter pub get
复制代码


接下来,我们需要在main.dart文件中创建一个新的 Material 应用程序:


import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Material App', home: Scaffold( appBar: AppBar( title: Text('Material App Bar'), ), body: Center( child: Container( child: Text('Hello World'), ), ), ), ); }}
复制代码

管理状态数据

现在,创建一个包含应用程序所需状态数据的新类。让我们命名它UserDetailsProvider。该UserDetailsProvider类将处理所有涉及此处理状态的方法。


这个类扩展了ChangeNotifier类;ChangeNotifier为我们提供对notifyListeners方法的访问,我们将使用该方法通知监听小部件在状态更改时重建。


我们为TextFormField:name和声明了两个控制器age。该类中还声明了根据用户输入更新用户姓名和年龄的方法。


处理应用程序状态的所有内容都在此处声明:


class UserDetailsProvider extends ChangeNotifier { TextEditingController nameController = TextEditingController(); TextEditingController ageController = TextEditingController(); int _age = 0; String _userName = ''; int get userAge => _age; String get userName => _userName; void updateAge(int age) { _age = age; notifyListeners(); } void updateName(String name) { _userName = name; notifyListeners(); }}
复制代码

更新状态

名称更新后,我们调用该notifyListeners方法,该方法将状态更改通知侦听小部件,从而触发所有相关小部件的重建。


现在我们有了UserDetailsProvider类(处理状态),我们需要使用ChangeNotifierProvider. 现在,在主块ChangeNotifierProviderrunApp方法中使用 a 包装整个应用程序。


ChangeNotifierProvider暴露了两个重要的特性:createchild。我们声明的类 extends ChangeNotifier,被传递到create属性中,将类链接到页面:


import 'package:flutter/material.dart';import 'package:provider/provider.dart';void main() => runApp(  ChangeNotifierProvider<UserDetailsProvider>(  create: (_) => UserDetailsProvider(),  child: MyApp(),  ), );// ignore: use_key_in_widget_constructorsclass MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return const MaterialApp(  title: 'Material App',  home: HomeScreen(), ); }}
复制代码


现在应用程序链接到提供状态的类;每当状态发生变化时,都会导致应用程序内页面的重建。

收集用户数据

目前,HomeScreen小部件包含一个带有两个TextFormFields 的表单,用于接收用户的姓名和年龄。此外,RawMaterialButton还包含 在用户传递所需的详细信息后保存更改。


在这组小部件之后,我们有两个Text小部件显示用户给出的值。这两个小部件是唯一需要在应用程序状态发生变化时更新的小部件。


这意味着我们不需要在每次状态发生变化时重建每个屏幕。因此,我们需要一种方法来选择性地仅重建Text与状态变化有关的小部件。为此,我们有Consumer小部件。

有选择地更新状态

Consumer控件只允许子控件,而不在 widget 树影响其他部件重建。如前所述,我们只希望text显示用户提供的详细信息的小部件进行更新。


我们通过Text用 a 包装两个小部件ColumnbuilderConsumer小部件公开的函数处返回它来实现这一点:


Consumer<UserDetailsProvider>(  builder: (context, provider, child) {  return Column(   children: [   Text(    'Hi ' + provider.userName,    style: const TextStyle(    fontSize: 18,    fontWeight: FontWeight.bold,    ),   ),   Text(    'You are ' + provider.userAge.toString() + ' years old',    style: const TextStyle(    fontSize: 18,    fontWeight: FontWeight.w400,    ),   ),   ],  );  }, ),
复制代码


现在,Text每当应用程序中的状态发生变化时,只有小部件会更新。


确保尽可能使用最低级别的提供程序;您只能将提供程序用于受影响的小部件。在高级别使用它会导致不关心状态更改的小部件重建。与Consumer小部件相同的事情;确保您在特定级别使用以避免重建整个小部件树。


我们的示例应用程序终于准备好了!

结论

强调 Flutter 中状态管理的重要性怎么强调都不为过。今天,我们剖析了 Provider 包并使用它来管理示例 Flutter 应用程序的状态。希望通过在本文构建应用程序所获得的实践知识,您现在可以以一种干净,快速且更易于访问的方式正确管理应用程序的状态。


发布于: 2021 年 11 月 27 日阅读数: 10
用户头像

坚果前端

关注

此间若无火炬,我便是唯一的光 2020.10.25 加入

公众号:“坚果前端”,51CTO博客首席体验官,专注于大前端技术的分享,包括Flutter,小程序,安卓,VUE,JavaScript。

评论

发布
暂无评论
Flutter 状态管理Provider快速指南【Flutter 专题 8】