如何在Flutter Riverpod中用自定义状态替换AsyncNotifier默认AsyncValue
用自定义UIState替换Riverpod AsyncNotifier的默认AsyncValue状态
两种实现方案
方案一:改用Notifier完全替换状态类型
AsyncNotifier的设计就是绑定AsyncValue作为状态的,如果你想让状态直接是自定义的UIState<ExploreModel>,应该使用普通的Notifier而非AsyncNotifier:
@riverpod class ExploreController extends _$ExploreController { @override UIState<ExploreModel> build() { // 设置初始状态为加载中 return const UIState.loading(); } // 异步获取数据的方法 Future<void> fetchExploreData() async { try { // 手动设置加载状态 state = const UIState.loading(); final result = await getExploreModel(); state = UIState.success(data: result); } catch (e) { // 捕获错误并设置错误状态 state = UIState.error(message: e.toString()); } } // 刷新数据的方法 Future<void> refreshData() async { await fetchExploreData(); } }
使用时直接监听状态:
ref.watch(exploreControllerProvider).when( loading: () => const CircularProgressIndicator(), success: (data) => ExploreView(data: data), error: (message) => Text('出错了:$message'), );
方案二:保留AsyncNotifier,将自定义UIState作为AsyncValue的泛型参数
如果一定要用AsyncNotifier(比如想利用它的异步自动状态管理),可以把UIState<ExploreModel>作为AsyncValue的内层类型,此时状态是AsyncValue<UIState<ExploreModel>>:
@riverpod class ExploreController extends _$ExploreController { @override Future<UIState<ExploreModel>> build() async { final result = await getExploreModel(); return UIState.success(data: result); } Future<void> refresh() async { // 利用AsyncNotifier的异步状态自动处理,会自动设置loading状态 state = const AsyncValue.loading(); try { final result = await getExploreModel(); state = AsyncValue.data(UIState.success(data: result)); } catch (e, stackTrace) { state = AsyncValue.error(e, stackTrace); // 也可以把错误包装到自定义UIState里 // state = AsyncValue.data(UIState.error(message: e.toString())); } } }
使用时需要先处理外层的AsyncValue,再处理内层的UIState:
ref.watch(exploreControllerProvider).when( loading: () => const CircularProgressIndicator(), error: (e, _) => Text('请求失败:$e'), data: (uiState) => uiState.when( loading: () => const CircularProgressIndicator(), success: (data) => ExploreView(data: data), error: (message) => Text('数据解析错误:$message'), ), );
关键说明
- AsyncNotifier的核心特性就是自动管理
AsyncValue状态(加载/成功/错误),如果不需要外层的AsyncValue,直接用普通Notifier更贴合需求。 - 自定义
UIState需要实现类似when的方法(模仿AsyncValue的API),方便在UI层根据状态渲染不同界面。
内容的提问来源于stack exchange,提问作者Cyrus the Great
相关产品推荐
相关产品推荐

