下面是一个完整的例子,演示如何在 Riverpod 中:
- 在一个组件(WidgetA)中更新状态。
- 在另一个组件(WidgetB)中获取更新后的状态。
我们将使用 riverpod
+ flutter_riverpod
,并基于最新的 Riverpod 2.0 语法(推荐使用代码生成 @riverpod
)。
1. 定义 Provider
首先,创建一个状态管理 Provider(使用 @riverpod
代码生成)。
counter_provider.dart
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'counter_provider.g.dart';
// 定义一个 Counter 状态管理类
class Counter extends _$Counter {
// 初始状态
int build() => 0;
// 更新状态的方法
void increment() => state++;
}
运行代码生成:
dart run build_runner watch
这会生成 counter_provider.g.dart
,包含一个全局可用的 counterProvider
。
2. 在 WidgetA 中更新状态
创建一个按钮组件,点击时调用 increment()
更新状态。
widget_a.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'counter_provider.dart';
class WidgetA extends ConsumerWidget {
const WidgetA({super.key});
Widget build(BuildContext context, WidgetRef ref) {
return ElevatedButton(
onPressed: () {
// 通过 ref 读取 Counter 并调用方法更新状态
ref.read(counterProvider.notifier).increment();
},
child: const Text('Increment Counter'),
);
}
}
3. 在 WidgetB 中获取状态
另一个组件监听 counterProvider
的状态变化,并实时显示最新值。
widget_b.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'counter_provider.dart';
class WidgetB extends ConsumerWidget {
const WidgetB({super.key});
Widget build(BuildContext context, WidgetRef ref) {
// 监听 counterProvider 的状态变化
final counter = ref.watch(counterProvider);
return Text(
'Current Count: $counter',
style: Theme.of(context).textTheme.headlineMedium,
);
}
}
4. 整合到主页面
将两个组件放在同一个页面中测试。
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'widget_a.dart';
import 'widget_b.dart';
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Riverpod Example')),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
WidgetB(), // 显示状态
SizedBox(height: 20),
WidgetA(), // 更新状态
],
),
),
),
);
}
}
效果
- 点击
WidgetA
的按钮时,Counter
状态会递增。 WidgetB
会自动刷新并显示最新的计数器值。
关键点说明
ref.read()
vsref.watch()
:ref.read()
:一次性读取状态(适合触发方法,如按钮点击)。ref.watch()
:监听状态变化并自动重建组件(适合显示数据)。
.notifier
:- 通过
ref.read(counterProvider.notifier)
获取Counter
实例,才能调用其方法(如increment()
)。
- 通过
ProviderScope:
- 必须在应用的根节点包裹
ProviderScope
,这是 Riverpod 的核心上下文。
- 必须在应用的根节点包裹
通过这个例子,你可以清晰看到 Riverpod 的状态更新和跨组件共享状态的流程。