Flutter 使用Riverpod 进行状态管理

25 min read

添加依赖项

dependencies:
    flutter_riverpod: ^1.0.3

使用ProviderScope包裹应用程序

在 RiverPod 中,我们在全局范围内声明所有 Providers(将在前面讨论)。因此,RiverPod 会自动搜索所有 Provider 并将它们有效地注入到 Widget Tree 中。要在整个项目中启用 Riverpod 依赖项,我们需要在 ProviderScope 中包裹应用程序

void main() {
  runApp(
      const ProviderScope(
        child: MyApp(),
      ),
  }

Riverpod 的基本术语

Consumer:Consumer 只是一个订阅 Provider 的 Widget。顾名思义,它使用任何 Provider 发布的事件。

Provider:Provider 是 Riverpod 最重要的组件。简而言之,可以将 Provider 视为共享状态的访问点。类似于我们在使用 provider 包时创建的 Providers。

WidgetRef:WidgetRef 是 Riverpod 提供给我们的对象,可用于与 Providers 进行交互。我们将使用 WidgetRef 在我们的 Provider 上执行所有操作(修改、监听)。

Riverpod计数器应用程序

  1. 创建扩展 ChangeNotifier 的数据类
import 'package:flutter/foundation.dart';

class CounterNotifier extends ChangeNotifier {
  int value = 0;

  void increment() {
    value++;
    notifyListeners();
  }
}
  1. 声明 Provider
final counterProvider = ChangeNotifierProvider((ref) => CounterNotifier());
  1. 继承ConsumerWidget
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_example/data/change_counter.dart';

// 1 声明 ChangeNotifierProvider 并将其存储在一个变量中。
final counterProvider = ChangeNotifierProvider((ref) => CounterNotifier());

// 2 继承自 ConsumerWidget 以便获得 WidgetRef 实例
class ChangeCounterPage extends ConsumerWidget {
  const ChangeCounterPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 3 ref.read() 来访问 Data Class 的单例实例并对其执行可用的操作
          ref.read(counterProvider).increment();
        },
        child: const Icon(Icons.add),
      ),
      body: Center(
        // 4 ref.watch() 来获取提供者的值并订阅未来的事件
        child: Text(ref.watch(counterProvider).value.toString()),
      ),
    );
  }
}

ProviderScope 的overrides

overrides 方法允许在设置一个 ProviderScope 时覆盖现有状态。它接受一个代码块,并在此代码块内部执行一次更新。

举个例子,如果有一个名为 counter 的 Provider ,我们可以在 ProviderScope 中使用 overrides 方法来更新它的值:

ProviderScope(
  overrides: [
    counter.override(value: 3),
  ],
  child: ...,
)

这意味着在整个 ProviderScope 的范围内, counter 的值将被更新为 3,直到该 ProviderScope 结束。

ProviderScope(
      overrides: [
        deviceRawInfoProvider.overrideWithValue(await getDeviceInfo()),
        persistenceProvider.overrideWithValue(persistenceService),
        appArgumentsProvider.overrideWith((ref) => args),
      ],
      child: const LocalSendApp(),
    ),