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

Flutter教程:如何为Future Builder的ListView添加分页功能

Flutter 列表分页实现(适配你的业务场景)

核心问题拆解

你的代码无法实现分页加载的核心原因:

  1. 没有维护本地数据集,每次请求都是重新获取数据而非追加到现有列表
  2. API请求未携带分页参数,无法获取对应页码的数据
  3. 缺少加载状态控制,容易重复触发加载请求
  4. 未实现正确的加载更多逻辑,且存在方法调用语法错误

修改后的完整代码

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:xsocial/utils/my_drawer.dart';
import 'package:xsocial/utils/transaction_history_tile.dart';
import 'package:http/http.dart' as http;

class TransactionHistory extends StatefulWidget {
  const TransactionHistory({super.key});

  @override
  State<TransactionHistory> createState() => _TransactionHistoryState();
}

class _TransactionHistoryState extends State<TransactionHistory> {
  final _controller = ScrollController();
  int _currentPage = 1;
  List<dynamic> _transactions = [];
  bool _isLoading = false;

  // 带分页参数的API请求方法
  Future<List> _getTransactionData(int page) async {
    final res = await http.get(Uri.parse(
        'http://194.143.45.195/myappi/cash-transaction-history?page=$page'));
    var resBody = jsonDecode(res.body);
    return resBody;
  }

  // 加载更多逻辑,处理数据追加、状态切换与错误提示
  Future<void> _loadMoreTransactions() async {
    if (_isLoading) return; // 防止重复加载
    setState(() => _isLoading = true);

    try {
      final newTransactions = await _getTransactionData(_currentPage);
      if (newTransactions.isNotEmpty) {
        setState(() {
          _transactions.addAll(newTransactions);
          _currentPage++;
        });
      } else {
        if (mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('已加载全部交易记录')),
          );
        }
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('加载失败:${e.toString()}')),
        );
      }
    } finally {
      if (mounted) {
        setState(() => _isLoading = false);
      }
    }
  }

  @override
  void initState() {
    super.initState();
    _loadMoreTransactions(); // 初始化加载第一页
    _controller.addListener(() {
      // 精准判断滚动到底部
      if (_controller.position.pixels == _controller.position.maxScrollExtent) {
        _loadMoreTransactions();
      }
    });
  }

  @override
  void dispose() {
    _controller.dispose(); // 清理控制器,避免内存泄漏
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          'Transaction History',
          style: TextStyle(fontWeight: FontWeight.bold),
        ),
      ),
      drawer: const MyDrawer(),
      body: Column(
        mainAxisSize: MainAxisSize.max,
        children: [
          // 搜索栏
          const SizedBox(height: 15.0),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 15.0),
            child: Container(
              decoration: BoxDecoration(
                color: Colors.grey[200],
                borderRadius: BorderRadius.circular(7),
              ),
              child: const TextField(
                decoration: InputDecoration(
                  prefixIcon: Icon(Icons.search),
                  border: InputBorder.none,
                  hintText: 'Search transactions by ID',
                ),
              ),
            ),
          ),
          const SizedBox(height: 15.0),
          // 交易列表区域
          Expanded(
            child: _transactions.isEmpty && !_isLoading
                ? const Center(child: Text('暂无交易记录'))
                : ListView.builder(
                    controller: _controller,
                    itemCount: _transactions.length + (_isLoading ? 1 : 0),
                    itemBuilder: (context, index) {
                      if (index == _transactions.length) {
                        // 底部加载指示器
                        return const Padding(
                          padding: EdgeInsets.symmetric(vertical: 16.0),
                          child: Center(child: CircularProgressIndicator()),
                        );
                      }
                      // 适配你的TransactionHistoryTile组件,若原组件接收列表可改为list: [_transactions[index]]
                      return TransactionHistoryTileItem(
                          transaction: _transactions[index]);
                    },
                  ),
          ),
        ],
      ),
    );
  }
}

关键修改说明

  1. 本地状态管理:新增_transactions列表存储所有已加载数据,_isLoading控制加载状态,避免重复请求
  2. 分页API适配:修改请求方法,添加page参数,确保后端返回对应页码的数据
  3. 加载逻辑优化:实现_loadMoreTransactions方法,处理数据追加、错误捕获与用户提示
  4. 滚动监听调整:改用maxScrollExtent判断底部,避免顶部边缘的误触发
  5. 列表展示优化:用ListView.builder替代单纯的FutureBuilder,分页场景下本地维护状态更灵活,同时添加无数据、加载中的状态提示
  6. 内存泄漏防护:在dispose方法中销毁ScrollController

内容的提问来源于stack exchange,提问作者Cliff Odebala Clarke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 21:59:52