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
相关产品推荐
相关产品推荐

