You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 16:27:32