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

如何用Riverpod与Freezed合并两个API请求状态?

合并两个API请求状态的实现方案

针对你需要合并两个API请求状态的需求,这里提供一套基于Riverpod和Freezed的实现方案,完全匹配你要求的逻辑:双请求都成功才触发成功状态,任一失败则进入错误状态,其余情况保持加载。

1. 定义合并后的全局状态类

首先创建一个Freezed状态类,用来表示两个API请求的整体状态,成功状态需要同时持有两个接口返回的实体:

import "package:freezed_annotation/freezed_annotation.dart";
import "...features/profile/domain/entities/user_profile_entity.dart";
import "...features/profile/domain/entities/user_properties_entity.dart";

part "combined_profile_state.freezed.dart";

@freezed
class CombinedProfileState with _$CombinedProfileState {
  /// 初始状态
  const factory CombinedProfileState.initial() = _CombinedProfileStateInitial;

  /// 加载中(任一请求未完成)
  const factory CombinedProfileState.loading() = _CombinedProfileStateLoading;

  /// 双请求均成功
  const factory CombinedProfileState.success({
    required ProfileEntity profile,
    required UserPropertiesEntity properties,
  }) = _CombinedProfileStateSuccess;

  /// 任一请求失败
  const factory CombinedProfileState.error([String? message]) = _CombinedProfileStateError;
}

2. 创建组合状态Provider

通过Riverpod的Provider监听两个子Notifier的状态变化,实时推导整体状态:

import "package:riverpod_annotation/riverpod_annotation.dart";
import "user_profile_details_notifier.dart";
import "user_properties_notifier.dart";
import "combined_profile_state.dart";

part "combined_profile_provider.g.dart";

@riverpod
CombinedProfileState combinedProfile(CombinedProfileRef ref) {
  // 监听两个子状态的实时变化
  final profileState = ref.watch(userProfileDetailsNotifierProvider);
  final propertiesState = ref.watch(userPropertiesNotifierProvider);

  // 检查是否有请求出错
  final profileError = profileState.maybeWhen(
    error: (msg) => msg,
    orElse: () => null,
  );
  final propertiesError = propertiesState.maybeWhen(
    error: (msg) => msg,
    orElse: () => null,
  );

  if (profileError != null) {
    return CombinedProfileState.error(profileError);
  }
  if (propertiesError != null) {
    return CombinedProfileState.error(propertiesError);
  }

  // 检查是否两个请求都返回了有效数据
  final profileData = profileState.maybeWhen(
    data: (profile) => profile,
    orElse: () => null,
  );
  final propertiesData = propertiesState.maybeWhen(
    data: (props) => props,
    orElse: () => null,
  );

  if (profileData != null && propertiesData != null) {
    return CombinedProfileState.success(
      profile: profileData,
      properties: propertiesData,
    );
  }

  // 其余情况(初始、单个请求加载中)返回加载状态
  return const CombinedProfileState.loading();
}

3. 页面中使用组合状态

在页面Widget中直接监听这个组合Provider,根据整体状态渲染对应UI:

class ProfilePage extends ConsumerWidget {
  const ProfilePage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final combinedState = ref.watch(combinedProfileProvider);

    return combinedState.when(
      initial: () => const SizedBox.shrink(),
      loading: () => const Center(child: CircularProgressIndicator()),
      success: (profile, properties) {
        // 渲染成功页面,使用两个接口返回的数据
        return Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text("用户名:${profile.name}"),
            Text("账户设置:${properties.settings}"),
            // 其他UI元素
          ],
        );
      },
      error: (msg) {
        return Center(child: Text(msg ?? "加载失败,请重试"));
      },
    );
  }
}

4. 保留原有Token失效逻辑

你原代码中的TokenFailure处理逻辑无需修改,两个子Notifier中已经实现了Token失效时的登出操作,组合状态会自动感知到错误状态,但登出逻辑已经在子Notifier中独立完成。

额外说明

  • 两个子Notifier的build方法中自动发起请求的逻辑保持不变,页面初始化时两个API会同时触发请求。
  • 组合状态会自动响应任一子状态的变化,实时更新整体状态,无需手动触发刷新。

内容的提问来源于stack exchange,提问作者patana93

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 13:17:19