什麼是 Riverpod?

Riverpod 是由 Remi Rousselet 創建的一個強大且靈活的狀態管理解決方案。它旨在解決 Provider 包的一些限制,提供更好的可測試性、更多的靈活性和更少的全局狀態依賴。

安裝

在你的 Flutter 項目中添加  flutter_riverpod  依賴項。

1
2
3
4
dependencies:
flutter:
sdk: flutter
flutter_riverpod: ^1.0.0

然後運行以下命令來安裝依賴項:

1
flutter pub get

基本用法

1. 創建 Provider

Provider 是 Riverpod 中的核心概念,用於管理應用程序的狀態。以下是一個簡單的計數器 Provider:

1
2
3
4
5
6
import 'package:flutter_riverpod/flutter_riverpod.dart';

// 創建一個 StateProvider
final counterProvider = StateProvider<int>((ref) {
return 0;
});

2. 使用 ProviderScope

ProviderScope  是一個 Widget,用於提供一個狀態作用域,該作用域內的所有 Provider 都可以共享相同的狀態。通常將  ProviderScope  放在應用程序的根部。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

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

class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}

3. 使用 ConsumerWidget

ConsumerWidget  是一個 Widget,用於訪問和使用 Provider 的狀態。你可以在  build  方法中使用  ref.watch  來監聽 Provider 的狀態變化,並使用  ref.read  來更新狀態。

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
class HomePage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// 使用 Provider 來訪問狀態
final counter = ref.watch(counterProvider);

return Scaffold(
appBar: AppBar(
title: Text('Riverpod Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Counter: $counter'),
ElevatedButton(
onPressed: () {
// 使用 Provider 來更新狀態
ref.read(counterProvider.state).state++;
},
child: Text('Increment'),
),
],
),
),
);
}
}

進階用法

1. 使用 StateNotifierProvider

StateNotifierProvider  用於管理更複雜的狀態。你可以創建一個  StateNotifier  類來管理狀態,並使用  StateNotifierProvider  提供這個狀態。

1
2
3
4
5
6
7
8
9
10
11
12
13
import 'package:flutter_riverpod/flutter_riverpod.dart';

// 創建一個 StateNotifier 類
class CounterNotifier extends StateNotifier<int> {
CounterNotifier() : super(0);

void increment() => state++;
}

// 創建一個 StateNotifierProvider
final counterNotifierProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
return CounterNotifier();
});

2. 使用 Provider 類型

Riverpod 提供了多種 Provider 類型來管理不同的狀態:

Provider:用於提供只讀的狀態。StateProvider:用於提供可變的狀態。FutureProvider:用於管理異步狀態。StreamProvider:用於管理流狀態。StateNotifierProvider:用於管理更複雜的狀態。

程式範例

以下是一個完整的範例,展示如何使用  StateNotifierProvider  來管理計數器狀態:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

// 創建一個 StateNotifier 類
class CounterNotifier extends StateNotifier<int> {
CounterNotifier() : super(0);

void increment() => state++;
}

// 創建一個 StateNotifierProvider
final counterNotifierProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
return CounterNotifier();
});

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

class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}

class HomePage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// 使用 Provider 來訪問狀態
final counter = ref.watch(counterNotifierProvider);

return Scaffold(
appBar: AppBar(
title: Text('Riverpod Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Counter: $counter'),
ElevatedButton(
onPressed: () {
// 使用 Provider 來更新狀態
ref.read(counterNotifierProvider.notifier).increment();
},
child: Text('Increment'),
),
],
),
),
);
}
}

總結

ProviderScope:提供一個狀態作用域,該作用域內的所有 Provider 都可以共享相同的狀態。Provider 類型:包括  ProviderStateProviderFutureProviderStreamProvider  和  StateNotifierProvider