# Flutter 好用package - hooks_riverpod
```
flutter pub add hooks_riverpod
```
hooks_riverpod 可以想成 riverpod + hooks,
[官網](https://pub.dev/packages/hooks_riverpod)
## 建議安裝套件有以下:
```yaml
dependencies:
hooks_riverpod: ^2.3.6
freezed_annotation: ^2.2.0
dev_dependencies:
build_runner: ^2.3.3
freezed: ^2.3.5
```
[官網](https://pub.dev/packages/hooks_riverpod)
## 範例 - Counter(點擊按鈕以後進行累加)
main.dart,添加 `ProviderScope` 才可以使用
```dart
Future<void> main() {
runApp(
const ProviderScope(
child: MyApp(),
),
);
}
```
counter_provider.dart,添加累加功能
```dart
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
part 'counter_provider.freezed.dart';
@freezed
abstract class CounterProviderState with _$CounterProviderState {
const factory CounterProviderState({
@Default(0) int count,
}) = _CounterProviderState;
const CounterProviderState._();
}
final countProvider =
StateNotifierProvider<CounterProviderNotifier, CounterProviderState>(
(ref) => CounterProviderNotifier());
class CounterProviderNotifier extends StateNotifier<CounterProviderState> {
CounterProviderNotifier() : super(const CounterProviderState());
increment() {
int count = state.count + 1;
state = state.copyWith(count: count);
}
}
```
counter_provider.freezed.dart,輸入下述指令就會自動生成此檔案:
```
dart run build_runner build
```
main.dart,監聽當前點擊次數使用 `watch`
```dart
Text(
'${ref.watch(countProvider).count}',
style: Theme.of(context).textTheme.headlineMedium,
),
```
main.dart,點擊事件使用 `read`
```dart
floatingActionButton: FloatingActionButton(
onPressed: ref.read(countProvider.notifier).increment,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
```
## 範例-顯示不同狀態的UI
### 預設不需定義
### 自定義
```dart
@freezed
abstract class ExampleListState with _$ExampleListState {
const factory ExampleListState.loading() = _ExampleListStateLoading;
const factory ExampleListState.data(
{required List<AppSimpleInfo>? appInfo}) = _ExampleListStateData;
const factory ExampleListState.empty() = _ExampleListStateEmpty;
const factory ExampleListState.error({required String msg}) =
_ExampleListStateError;
}
final exampleListProvider =
StateNotifierProvider<AppDownloadListNotifier, ExampleListState>(
(ref) => AppDownloadListNotifier());
class AppDownloadListNotifier extends StateNotifier<ExampleListState> {
AppDownloadListNotifier() : super(const ExampleListState.loading());
load() async {
state = const ExampleListState.loading();
Response? response;
try {
response = await ApiService.exampleList(isIOS: Platform.isIOS);
} on DioException catch (e, stacktrace) {
response = e.response;
state = ExampleListState.error(
msg: ' [${response != null ? response.statusCode : e.type}]');
logger.e('exampleList 請求發生錯誤(${e.message})', e, stacktrace);
}
try {
if (response != null && response.statusCode == 200) {
DownloadListResponse model =
DownloadListResponse.fromJson(response.data);
final data = model.data;
if (data != null) {
state = ExampleListState.data(
appInfo: data,
);
} else {
state = const ExampleListState.empty();
}
}
} catch (e, stacktrace) {
state = const ExampleListState.error(msg: ' [解析錯誤]');
logger.e('exampleList 解析內容發生錯誤', e, stacktrace);
}
}
}
```
## 參考資料
https://yiichenhi.medium.com/riverpod-%E8%BC%95%E9%AC%86%E5%AD%B8-%E5%8E%9F%E4%BE%86%E9%80%99%E9%BA%BC%E5%A5%BD%E7%94%A8-7e7b231570bc
###### tags: `flutter`