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

如何用单个Bloc管理单页面15个API状态?求最佳实践

多API场景下的状态管理最佳实践

首页需要调用15个API接口,当前实现是为每个API创建单独的Status抽象类(如Api1Status、Api2Status),并将这些Status作为HomeState的构造参数,通过buildWhen管理组件构建逻辑,但这种方式导致代码冗余、结构复杂。当前核心代码如下:

当前HomeState实现

class HomeState {
  Api1Status? api1status;
  Api2Status? api2Status;

  HomeState({
    this.api1status,
    this.api2Status,
  });

  HomeState copyWith({
    Api1Status? newApi1status,
    Api2Status? newApi2Status,
  }) {
    return HomeState(
      api1status: newApi1status ?? this.api1status,
      api2Status: newApi2Status ?? this.api2Status,
    );
  }
}

当前单个API状态类实现

@immutable
abstract class Api1Status{}

class Api1Loading extends Api1Status{}

class Api1Completed extends Api1Status{
  final Api1Entity Api1Entity;
  Api1Completed(this.Api1Entity);
}

class Api1Error extends Api1Status{
  final String message;
  Api1Error(this.message);
}

优化方案:通用化+结构化处理

1. 用泛型封装通用API状态类

创建一套通用的泛型状态类,替代每个API单独定义的Status,彻底消除重复代码:

@immutable
abstract class ApiStatus<T> {}

class ApiLoading<T> extends ApiStatus<T> {}

class ApiCompleted<T> extends ApiStatus<T> {
  final T data;
  ApiCompleted(this.data);
}

class ApiError<T> extends ApiStatus<T> {
  final String message;
  ApiError(this.message);
}

2. 优化HomeState结构

根据业务需求选择以下两种结构:

方式一:明确字段的泛型状态(推荐)

适合需要清晰区分每个API状态的场景,比原实现简洁且类型安全:

class HomeState {
  final ApiStatus<Api1Entity>? api1Status;
  final ApiStatus<Api2Entity>? api2Status;
  // ... 其余13个API的泛型状态字段

  HomeState({
    this.api1Status,
    this.api2Status,
    // ... 其余字段初始化
  });

  HomeState copyWith({
    ApiStatus<Api1Entity>? api1Status,
    ApiStatus<Api2Entity>? api2Status,
    // ... 其余字段的copy参数
  }) {
    return HomeState(
      api1Status: api1Status ?? this.api1Status,
      api2Status: api2Status ?? this.api2Status,
      // ... 其余字段赋值
    );
  }
}

方式二:Map存储动态状态(适合API数量极多的场景)

如果API数量后续可能持续扩展,用Map存储状态更灵活,同时封装获取方法保证类型安全:

class HomeState {
  final Map<String, ApiStatus<Object>> apiStates;

  HomeState({this.apiStates = const {}});

  HomeState copyWith({Map<String, ApiStatus<Object>>? apiStates}) {
    return HomeState(
      apiStates: {...this.apiStates, ...?apiStates},
    );
  }

  // 封装类型安全的状态获取方法
  ApiStatus<T>? getApiStatus<T>(String key) {
    return apiStates[key] as ApiStatus<T>?;
  }
}

使用示例:

// 更新api1为加载状态
state.copyWith(apiStates: {'api1': ApiLoading<Api1Entity>()});
// 更新api1为完成状态
state.copyWith(apiStates: {'api1': ApiCompleted<Api1Entity>(api1Data)});

3. 简化UI层buildWhen逻辑

封装通用的状态对比工具方法,避免每个BlocBuilder重复写判断逻辑:

// 通用判断方法:判断两个API状态是否需要触发重建
bool shouldRebuildApiStatus<T>(ApiStatus<T>? prev, ApiStatus<T>? current) {
  if (prev.runtimeType != current.runtimeType) return true;
  if (prev is ApiCompleted<T> && current is ApiCompleted<T>) {
    return prev.data != current.data; // 需确保实体类重写==运算符
  }
  if (prev is ApiError<T> && current is ApiError<T>) {
    return prev.message != current.message;
  }
  return false;
}

在UI层使用:

BlocBuilder<HomeBloc, HomeState>(
  buildWhen: (prev, current) => shouldRebuildApiStatus(prev.api1Status, current.api1Status),
  builder: (context, state) {
    final status = state.api1Status;
    if (status is ApiLoading) {
      return const CircularProgressIndicator();
    } else if (status is ApiCompleted) {
      return Text(status.data.title);
    } else if (status is ApiError) {
      return Text(status.message);
    }
    return const SizedBox();
  },
)

4. 进阶优化:拆分状态到子Bloc

如果首页业务模块复杂,可将不同业务域的API拆分到单独子Bloc(如BannerBloc、RecommendBloc),每个子Bloc管理自己的API状态,首页通过MultiBlocBuilder组合多个Bloc,进一步降低单个HomeState的复杂度。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 12:03:30