Riverpod

Riverpod是由Provider的开发者为了简化使用流程,彻底重构的全新状态管理框架。

安装

1
2
3
4
5
6
flutter pub add flutter_riverpod
flutter pub add riverpod_annotation
flutter pub add dev:riverpod_generator
flutter pub add dev:build_runner
flutter pub add dev:custom_lint
flutter pub add dev:riverpod_lint

Provider(提供者)

Provider构建在InheritedWidget之上,Provider 利用 InheritedWidget 的功能自动将值沿着 widget 树传播,确保每当状态发生变化时相关的 widget 都会得到更新。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Counter with ChangeNotifier {
int _count = 0;

int get count => _count;

void increment() {
_count++;
notifyListeners();
}
}

class CounterWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counter = Provider.of<Counter>(context);

return Text('Count: ${counter.count}');
}
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => Counter(),
child: CounterWidget(),
);
}
}

Riverpod

Riverpod引入了新的概念,不同于Provider,不需要context,更方便。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
final counterProvider = ChangeNotifierProvider((ref) => Counter());

class CounterWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
final counter = watch(counterProvider);

return Text('Count: ${counter.count}');
}
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ProviderScope(
child: MaterialApp(
home: CounterWidget(),
),
);
}
}

代码来源于Provider vs. Riverpod. When it comes to developing Flutter… | by Balaji Venkatachalam | Medium

使用

1
2
3
4
5
6
void main() {
runApp(
// 添加 ProviderScope 使得整个项目可以使用 Riverpod
const ProviderScope(child: MyApp()),
);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/// 使用 `@riverpod` 注解一个类定义了应用程序的新共享状态,
/// 可以通过生成的 [counterProvider] 来访问。
/// 这个类负责初始化状态(通过 [build] 方法)以及提供修改状态的方式(例如 [increment])。
@riverpod
class Counter extends _$Counter {
/// `@riverpod` 注解的类**必须**定义一个 [build] 函数。
/// 这个函数应该返回共享状态的初始值。
/// 如果需要,这个函数可以返回一个 [Future] 或 [Stream]。
/// 你也可以自由地在这个方法上定义参数。
@override
int build() => 0;

void increment() => state++;
}

class Home extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(title: const Text('计数器示例')),
body: Center(
child: Text('${ref.watch(counterProvider)}'),
),
floatingActionButton: FloatingActionButton(
// read 方法是一个工具,用于读取一个 provider 而不需要监听它
onPressed: () => ref.read(counterProvider.notifier).increment(),
child: const Icon(Icons.add),
),
);
}
}