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

Flutter中为Wrap组件实现大数据分页以提升性能

解决Flutter中Wrap组件加载大量数据卡顿的分页实现方案

核心思路

Wrap组件没有类似ListView.builder的按需构建机制,一次性渲染上千个Chip必然导致卡顿。我们可以通过手动维护分批加载的数据集,结合滚动监听触发后续加载,既保留Wrap的流式布局特性,又避免一次性创建所有Widget。

具体实现步骤

1. 添加状态变量

在你的State类中新增以下变量,用于控制分页加载:

// 存储当前已加载的职业数据
List<String> loadedOccupations = [];
// 每页加载的数量,可根据实际情况调整
final int _pageSize = 50;
// 标记是否正在加载,避免重复触发
bool _isLoading = false;

2. 初始化第一批数据

在initState中加载第一页数据:

@override
void initState() {
  super.initState();
  _loadMore();
}

void _loadMore() {
  if (_isLoading) return;
  
  setState(() => _isLoading = true);
  
  // 计算本次加载的起止索引
  final startIndex = loadedOccupations.length;
  final endIndex = startIndex + _pageSize > occupations.length 
      ? occupations.length 
      : startIndex + _pageSize;
  
  // 将新数据添加到已加载列表
  loadedOccupations.addAll(occupations.sublist(startIndex, endIndex));
  
  setState(() => _isLoading = false);
}

3. 改造Wrap布局,添加滚动监听

用SingleChildScrollView包裹Wrap,并通过NotificationListener监听滚动事件,当滚动到接近底部时自动加载下一页:

NotificationListener<ScrollNotification>(
  onNotification: (notification) {
    // 当滚动到当前内容高度的80%时触发加载(阈值可调整)
    if (notification.metrics.pixels / notification.metrics.maxScrollExtent > 0.8 && !_isLoading) {
      _loadMore();
    }
    return false;
  },
  child: SingleChildScrollView(
    child: Wrap(
      alignment: WrapAlignment.center,
      runAlignment: WrapAlignment.center,
      crossAxisAlignment: WrapCrossAlignment.center,
      spacing: 15,
      runSpacing: 15,
      children: [
        // 渲染已加载的职业Chip
        ...loadedOccupations.map((interest) {
          final isSelected = selectedInterests.contains(interest);
          return InkWell(
            enableFeedback: true,
            onTap: () {
              if (isSelected) {
                setState(() => selectedInterests.remove(interest));
              } else {
                if (selectedInterests.length < 8) {
                  setState(() => selectedInterests.add(interest));
                } else {
                  showToast(context, "You can only select 8 interests");
                }
              }
            },
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                Container(
                  padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
                  alignment: Alignment.center,
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(20),
                    color: isSelected 
                        ? theme.primary 
                        : theme.primary.withOpacity(0.04),
                    border: Border.all(width: 2, color: theme.primary),
                    boxShadow: const [
                      BoxShadow(
                        color: Color.fromRGBO(240, 245, 255, 0.56),
                        blurRadius: 10,
                        offset: Offset(0, 10),
                      )
                    ],
                  ),
                  child: CustomText(
                    interest,
                    color: isSelected ? Colors.white : Colors.grey[800],
                    fontSize: 14,
                    fontWeight: FontWeight.w500,
                  ),
                ),
              ],
            ),
          );
        }).toList(),
        // 可选:添加加载状态指示器
        if (_isLoading)
          const Padding(
            padding: EdgeInsets.all(16.0),
            child: CircularProgressIndicator(),
          )
      ],
    ),
  ),
)

优化建议

  • 可根据设备屏幕尺寸动态调整_pageSize,比如在小屏设备上减小每页加载数量;
  • 滚动触发加载的阈值(示例中为80%)可根据需求调整,比如设为90%延迟加载;
  • 如果数据来自网络请求,只需将_loadMore中的本地数据替换为网络请求逻辑即可;
  • 若需要支持下拉刷新,可在外层嵌套RefreshIndicator,重置loadedOccupations后重新加载第一页。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 16:50:35