flutter StateNotifier

1,280 阅读3分钟

虽然可能没有太多空间用于状态管理解决方案,但我在这里介绍另一个. StateNotifier 是 ValueNotifier 类的扩展。它修复了我们将在前面讨论的 ValueNotifier 中存在的预先存在的问题。 StateNotifier 主要与 Provider 或 Riverpod 等状态管理解决方案一起使用。在这篇文章中,我们将讨论如何在 Flutter 中使用 StateNotifier 以及对 StateNotifier 的需求。

需要 StateNotifier 吗?

您可能已将 ChangeNotifier 或 ValueNotifier 与 Provider 一起使用,它确实可以正常工作。虽然我们在使用它们时可能不会遇到任何致命错误,但这些实现存在一些问题。

  • ChangeNotifier 和 ValueNotifiers 是可变的,即类外的任何人都可以更改通知程序的状态。这种行为不是预期的,因为我们期望通过函数与数据交互。
  • 我们需要在使用 ChangeNotifier 时手动调用 notifyListeners()。

让我们看看 StateNotifier 的优势:

  • 本质上是不可变的。
  • 比较新旧状态并自动通知侦听器。
  • 单个数据修改点。

Flutter 中的 StateNotifier

正如我们所讨论的,StateNotifier 是 ValueNotifier 的扩展。与 ValueNotifier 一样,它也存储一个值并通知更改,只是 StateNotifier 是不可变的,而其他则不是。此外,StateNotifier 独立于 Flutter,因此也可以在您的 Dart 项目中使用。

现在不用多说,让我们添加使用 StateNotifier 所需的依赖项:

dependencies:
    state_notifier: ^0.7.2+1
    flutter_state_notifier: ^0.7.1

创建我们的第一个 StateNotifier

作为一个简单的示例,让我们为传统的 Counter 应用程序创建一个 StateNotifier。我们只需要简单地扩展 StateNotifier 来代替 ValueNotifier,我们就准备好了 StateNotifier 类。

image.png

就像我们在 ValueNotifier 类中使用“value”来获取当前状态一样,同样我们使用“state”关键字来访问 StateNotifier 类的当前状态。

import 'package:flutter_riverpod/flutter_riverpod.dart';

class StateCounter extends StateNotifier<int> {
  StateCounter() : super(0);

// Add all modification functions here 
// as we can't modify the data from outside

  void increment() {
    state++;
  }

  void decrement() {
    state--;
  }
}

与此处的 ValueNotifier 类似,我们也必须将 initialValue 传递给超级构造函数。现在我们已经准备好 StateCounter,让我们看看如何使用它。

在 Flutter 中使用 StateNotifier

为了简单地访问我们的 StateNotifier,我们将其声明为全局变量,以便我们可以跨多个页面访问单个实例。

请注意,声明全局变量不是一个好方法,因为我们应该在不使用时手动处理我们的对象。但是,当我们的应用程序退出时,全局变量会被处理掉。为了避免这个问题,我们将 StateNotifier 与 Provider 或 RiverPod 结合使用。

因此,为了简单起见,我们在这里使用全局变量:

class StateCounter extends StateNotifier<int>{...}

// Singleton Global Instance
final StateCounter myCounter = StateCounter();

为了使用我们的 StateCounter,我们将使用由 flutter_state_counter 包提供的 StateNotifierBuilder。

Flutter 中的 StateNotifierBuilder

StateNotifierBuilder 类似于 ValueNotifier 的 ValueNotifierBuilder。它将 StateNotifier 作为侦听器,并在值更改时重建 widget 树。 StateNotifierBuilder 的构造函数是:

const StateNotifierBuilder({
  Key? key,
  required this.builder,
  required this.stateNotifier,
  this.child,
})

我们只需在 stateNotifier 参数中传递我们的 StateNotifier。在 builder 参数中,我们获得了 StateNotifier 的当前值。我们可以通过我们的代码轻松理解 StateNotifierBuilder。

import 'package:flutter/material.dart';
import 'package:flutter_state_notifier/flutter_state_notifier.dart';
import 'package:state_notifier_example/data/state_counter.dart';
import 'package:state_notifier_example/pages/next_page.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("State Notifier Demo"),
      ),
      floatingActionButton: FloatingActionButton(
        // 1 ~
        onPressed: () => myCounter.increment(),
        child: const Icon(Icons.add),
      ),
      body: StateNotifierBuilder(
        stateNotifier: myCounter,
        builder: (context, value, child) {
          // 2 ~
          return Center(
            child: Text(value.toString()),
          );
        },
      ),
    );
  }
}

代码说明:

我们通过名称 myCounter 声明了全局 StateNotifier,因此我们可以轻松地在实例上使用 increment() 方法。

使用我们的 StateNotifierBuilder,我们专门只重建 Text,因为这是唯一在我们的值发生变化时发生变化的 widget 。

结论

这与 StateNotifier VS ChangeNotifier 或 StateNotifier VS ValueNotifier 无关。 StateNotifier 不会取代 ChangeNotifier 和 ValueNotifier,但是,它只是状态管理解决方案列表中的一个补充。 StateNotifier 的好处是它内置在 Riverpod 中。在一个正常的项目中,添加依赖项来实现类似于 ValueNotifier 的东西对我来说是没有意义的。因此,我们将用 Flutter 中的 StateNotifier 和 Riverpod 来扩展这篇文章。