为什么不应该在Flutter中使用全局变量?

178 阅读6分钟

全局变量似乎是美妙的Flutter程序组件,因为它们只需声明一次,就可以被程序中的每个函数访问。然而,这些变量的成本比你想象的要高,主要是因为:

  1. 如果你删除了一个全局变量,你必须在整个程序中进行搜索,重构每一个可以访问被删除的全局变量的函数
  2. 它们很难测试,因为你必须在测试用例之间重置它们
  3. 由于每个函数都可以修改全局变量,所以很难跟踪变化。

上述所有原因说明了为什么在Flutter中不应该使用全局变量。在本教程中,我们将详细了解全局变量的缺点,并学习如何以更有效的方式来管理状态。

目录

什么是Flutter中的全局变量?

全局变量是公共变量,可以被Flutter程序中的每个方法和对象访问。

全局变量是局部变量的替代品,局部变量是在一个方法中创建的,并在该方法中被访问。

本地变量和全局变量的区别在于,本地变量不能被同一程序中的其他方法访问--因此,与全局变量相比,本地变量的范围有限。

在Flutter中使用全局变量的缺点

在Flutter中使用全局变量一直受到质疑和批评,通常被认为是不好的做法。以下是使用全局变量所带来的缺点。

复杂的代码维护过程

改变或删除一个全局变量会引发一系列连锁反应,因为使用该全局变量的小部件和方法都会受到影响。

如果你想改变一个全局变量,你必须分析访问全局变量的每个部件会受到怎样的影响,并进行具体和必要的修改。

如果你删除了一个全局变量,你必须在整个程序中进行搜索,并重构每个可以访问被删除的全局变量的函数。

全局变量使单元测试很痛苦

如果你改变了一个有全局变量的模块,那么你将不得不为接下来的测试重新设置它。

要理解使用全局变量的遗留代码是很难的,要了解程序流程是如何运作的就更难了。你很难有效地测试你不理解的代码,而且调试也很困难,因为你不知道谁改变了全局变量。

全局变量导致了意大利面条式的代码

由于程序中的每个函数都可以修改全局变量,所以很难跟踪变化。如果您正在构建一个大型应用程序,那么在Flutter中使用全局变量的情况就会升级。即使您正在构建小型 Flutter 应用程序,全局变量也是一种灾难。

全局变量反对封装

全局变量使得封装无法实现,封装是一个OOP概念,将代码包装成一个单元。封装使代码安全且易于维护。如果你想有效地使用封装,你必须禁止全局变量。

规范全局变量需要大量的纪律,因为它们会产生意大利面条般的代码。然而,有一些开发人员会使用全局变量,因为他们在一个小团队中,在某些情况下不利于改变。

但是,无论应用程序的规模如何,当需要维护代码时,全局变量会带来挑战。如果有必要使用全局变量,至少要让它们成为不可变的。

在下一节中,你将学习状态管理库和包,这些库和包提出了更好的管理变量状态的方式,而不会伤害到维护程序。

如何以更好的方式管理状态

Flutter是一个跨平台的动态框架,收集和处理来自用户的数据。

从开关到单选按钮,数据状态必须得到有效管理。然而,全局变量给应用程序的数据流增加了复杂性。全局变量使数据很容易发生突变,这可能会导致处理从用户那里收集到的数据时出现混乱。

状态管理包,如provider ,可以用来缓解全局变量带来的问题。下面是一个状态包管理和库的列表,你可以用它来管理状态。

提供者状态管理包

状况管理器 provider状态管理器包被广泛用于收集小组件的状态数据,并在状态改变时更新小组件。

当使用提供者时,在数据突变的情况下,只有受影响的小部件会被更新。与处处变化的全局变量相比,提供者降低了复杂性。提供者从widget收集数据,并监听widget周围发生的数据变化。

这个包将应用程序的状态与用户界面分开,provider ,促进应用程序的维护和测试。

使用下面的代码片断来添加和使用provider 包插件:

dependencies:
  flutter:
    sdk: flutter

  provider: ^3.1.0

provider 包还允许你与多个类共享widget状态:

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => CartModel()),
        Provider(create: (context) => SomeOtherClass()),
      ],
      child: const MyApp(),
    ),
  );
}

GetX

GetX是一个轻量级的Flutter库,它可以促进可扩展性,因为它允许你将视图、依赖注入、表现层和依赖注入解耦。

它提供了以下功能:

  • 状态管理
  • 依赖性注入
  • 导航
  • 路线管理

如果您正在寻找一个节约资源和消耗最小的库,GetX是最适合您的。

要在您的Flutter应用程序中开始使用GetX,请在您的pubspec.yaml文件中添加get

dependencies:
  get:

接下来,导入使用GetX库函数和组件时需要的get 文件。

import 'package:get/get.dart';

Riverpod

Riverpod项目与provider 包类似 - 唯一的区别是它以单向方式分发数据。

这个状态管理器可以确保你的代码是可测试的,并且易于阅读,因为它消除了组合对象的嵌套。其特别之处在于它能在编译过程中检测出错误。这将节省你的时间,因为你将在运行时为你的应用程序增加缺陷之前修复错误。

Redux

Redux是一个库,可以帮助你有效地管理小部件的数据状态。Redux是一个架构,它以单向的方式执行跨部件的状态数据分配。这个库很好,因为它消除了状态的重复,你可以测试状态结果是否为真。

SetState 的方法

之前,我们只介绍了管理状态的Flutter包和库。

有一个叫做setState 的方法,当你的widget改变数据值时可以调用。它将导致UI根据新的状态而改变。你可以添加当状态改变时做一些事情的代码。这里是Flutter中setState 的一个基本实现。

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    _counter++;
    setState(() {});
  }

结语

在本教程中,我们已经详细了解了什么是全局变量,以及为什么我们不应该在Flutter中使用它们。此外,我们还探讨了各种状态管理库,你可以用来更有效地管理状态。