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

Flutter调用Rest Api展示卡片列表,如何实现每10项查看更多功能

实现Flutter Bloc模式下的列表分页加载(查看更多)

一、调整Bloc的事件与状态

首先在Bloc体系中新增分页相关的事件和状态字段,用来控制加载更多的逻辑:

1. 定义事件类

abstract class WalletHistoryEvent {}

class WalletHistoryFetchEvent extends WalletHistoryEvent {
  // 初始加载默认页码1,每页10条
  final int page;
  final int limit;

  WalletHistoryFetchEvent({this.page = 1, this.limit = 10});
}

class WalletHistoryLoadMoreEvent extends WalletHistoryEvent {
  final int page;
  final int limit;

  WalletHistoryLoadMoreEvent({required this.page, this.limit = 10});
}

2. 更新状态类

在原有状态基础上添加分页控制字段:

class WalletHistoryState extends Equatable {
  final WalletHistory? walletHistory;
  final bool isLoading;
  final bool isLoadingMore; // 加载更多的状态标记
  final bool hasMoreData; // 是否还有未加载的数据
  final int currentPage; // 当前已加载的页码

  const WalletHistoryState({
    this.walletHistory,
    this.isLoading = false,
    this.isLoadingMore = false,
    this.hasMoreData = true,
    this.currentPage = 1,
  });

  // 状态复制方法,用于状态更新
  WalletHistoryState copyWith({
    WalletHistory? walletHistory,
    bool? isLoading,
    bool? isLoadingMore,
    bool? hasMoreData,
    int? currentPage,
  }) {
    return WalletHistoryState(
      walletHistory: walletHistory ?? this.walletHistory,
      isLoading: isLoading ?? this.isLoading,
      isLoadingMore: isLoadingMore ?? this.isLoadingMore,
      hasMoreData: hasMoreData ?? this.hasMoreData,
      currentPage: currentPage ?? this.currentPage,
    );
  }

  @override
  List<Object?> get props => [walletHistory, isLoading, isLoadingMore, hasMoreData, currentPage];
}

二、修改Bloc逻辑处理分页请求

在Bloc的事件处理方法中,实现初始加载和加载更多的逻辑,调用仓库接口并合并数据:

class WalletHistoryBloc extends Bloc<WalletHistoryEvent, WalletHistoryState> {
  final WalletRepository walletRepository;

  WalletHistoryBloc(this.walletRepository) : super(const WalletHistoryState()) {
    on<WalletHistoryFetchEvent>(_onFetchWalletHistory);
    on<WalletHistoryLoadMoreEvent>(_onLoadMoreWalletHistory);
  }

  void _onFetchWalletHistory(WalletHistoryFetchEvent event, Emitter<WalletHistoryState> emit) async {
    emit(state.copyWith(isLoading: true));
    try {
      final response = await walletRepository.getWalletHistory(
        page: event.page,
        limit: event.limit,
      );
      // 判断是否还有更多数据:返回结果数量等于每页条数则还有更多
      final hasMore = response.result?.length == event.limit;
      emit(state.copyWith(
        walletHistory: response,
        isLoading: false,
        hasMoreData: hasMore,
        currentPage: event.page,
      ));
    } catch (e) {
      emit(state.copyWith(isLoading: false));
      // 可在此添加错误提示逻辑
    }
  }

  void _onLoadMoreWalletHistory(WalletHistoryLoadMoreEvent event, Emitter<WalletHistoryState> emit) async {
    // 避免重复加载或无数据时触发
    if (state.isLoadingMore || !state.hasMoreData) return;

    emit(state.copyWith(isLoadingMore: true));
    try {
      final response = await walletRepository.getWalletHistory(
        page: event.page,
        limit: event.limit,
      );
      // 合并新旧数据
      final newResult = List.from(state.walletHistory?.result ?? [])..addAll(response.result ?? []);
      final updatedHistory = state.walletHistory?.copyWith(result: newResult);
      // 更新是否还有更多数据
      final hasMore = response.result?.length == event.limit;

      emit(state.copyWith(
        walletHistory: updatedHistory,
        isLoadingMore: false,
        hasMoreData: hasMore,
        currentPage: event.page,
      ));
    } catch (e) {
      emit(state.copyWith(isLoadingMore: false));
      // 可在此添加加载失败提示逻辑
    }
  }
}

三、修改仓库层接口,支持分页参数

更新仓库中的请求方法,携带page和limit参数调用接口:

class WalletRepository {
  Future<WalletHistory> getWalletHistory({required int page, required int limit}) async {
    final response = await Dio().get(
      ApiConstants.fetchWalletHistory, // 替换为你的实际接口地址
      queryParameters: {
        'page': page,
        'limit': limit,
      },
    );
    return WalletHistory.fromJson(response.data);
  }
}

四、调整UI,添加“查看更多”按钮

修改原有的ListView代码,增加加载更多按钮或加载状态:

BlocBuilder<WalletHistoryBloc, WalletHistoryState>(
  builder: (context, state) {
    final itemCount = state.walletHistory?.result?.length ?? 0;
    // 若还有更多数据,列表总长度加1(用来显示加载更多按钮)
    final totalCount = state.hasMoreData ? itemCount + 1 : itemCount;

    return ListView.separated(
      shrinkWrap: true,
      physics: const NeverScrollableScrollPhysics(),
      itemBuilder: (context, index) {
        // 最后一个位置显示加载更多按钮或加载中状态
        if (index == itemCount) {
          if (state.isLoadingMore) {
            return const Center(child: CircularProgressIndicator());
          } else {
            return TextButton(
              onPressed: () {
                context.read<WalletHistoryBloc>().add(
                  WalletHistoryLoadMoreEvent(
                    page: state.currentPage + 1,
                  ),
                );
              },
              child: const Text('查看更多'),
            );
          }
        }
        // 正常列表项
        return WalletHistoryItem(
          walletHistory: state.walletHistory!.result![index]!,
        );
      },
      separatorBuilder: (context, index) => const SizedBox(height: 16),
      itemCount: totalCount,
    );
  },
)

五、触发初始加载

在页面初始化时,发送初始加载事件:

@override
void initState() {
  super.initState();
  context.read<WalletHistoryBloc>().add(WalletHistoryFetchEvent());
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 18:20:46