# 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`