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

Flutter无限滚动GridView项重复问题求助

GridView所有项内容重复的问题解决

核心问题分析

  1. 单一随机值导致全局重复:主页面FutureBuilder中仅生成一次random_pet,所有Random_Image_Card组件都接收同一个参数,自然显示完全相同的内容。
  2. 无限滚动逻辑失效:当前仅在滚动到底部时递增pageNumber并调用setState,但API.get_pets未使用pageNumber参数,也未合并新请求数据,无法实现真正的无限加载。
  3. FutureBuilder重复请求隐患:直接将API.get_pets(randomly_select_URL())作为future参数,页面每次重建都会触发新的API请求,造成资源浪费。

修复方案

1. 主页面代码修正

维护已加载数据列表实现分页累加,为每个项生成独立随机索引,修正无限滚动逻辑:

import 'package:flutter/material.dart';
import 'package:pet_store/utils/utils.dart';
import 'package:pet_store/widgets/random_pet_image.dart';
import 'webservice/API.dart';
import 'main.dart';

class Infinite_Scroll_Game extends StatefulWidget {
  const Infinite_Scroll_Game({Key? key}) : super(key: key);

  @override
  State<Infinite_Scroll_Game> createState() => _Infinite_Scroll_GameState();
}

class _Infinite_Scroll_GameState extends State<Infinite_Scroll_Game> {
  ScrollController _scrollController = ScrollController();
  int pageNumber = 1;
  List<dynamic> allPetData = [];
  bool isLoading = false;

  @override
  void initState() {
    super.initState();
    _fetchPetData();
    _scrollController.addListener(() {
      if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent && !isLoading) {
        pageNumber++;
        _fetchPetData();
      }
    });
  }

  void _fetchPetData() async {
    setState(() => isLoading = true);
    try {
      final newData = await API.get_pets(randomly_select_URL());
      setState(() {
        allPetData.addAll(newData);
        isLoading = false;
      });
    } catch (e) {
      setState(() => isLoading = false);
      // 按需添加错误提示逻辑
    }
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: AppBar(
        backgroundColor: Colors.indigo,
        title: const Text('Infinite Scroll Game'),
        leading: GestureDetector(
          child: const Icon(Icons.arrow_back_ios, color: Colors.white),
          onTap: () {
            Navigator.pushAndRemoveUntil(
              context,
              MaterialPageRoute(builder: (context) => const HomePage()),
              (route) => false,
            );
          },
        ),
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 12.0),
        child: allPetData.isEmpty 
            ? const Center(child: CircularProgressIndicator())
            : Stack(
              children: [
                GridView.builder(
                  controller: _scrollController,
                  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 2,
                    crossAxisSpacing: 12.0,
                    mainAxisSpacing: 12.0,
                  ),
                  itemCount: allPetData.length + (isLoading ? 1 : 0),
                  itemBuilder: (context, index) {
                    if (index == allPetData.length) {
                      return const Center(child: CircularProgressIndicator());
                    }
                    // 为每个项生成独立随机宠物索引
                    final randomPetIndex = random.nextInt(allPetData.length);
                    return Random_Image_Card(petData: allPetData[randomPetIndex]);
                  },
                ),
              ],
            ),
      ),
    );
  }
}

2. 卡片组件代码修正

直接接收单个宠物数据,组件内部独立处理图片随机选择:

import 'package:flutter/material.dart';
import 'package:pet_store/utils/utils.dart';

class Random_Image_Card extends StatefulWidget {
  final dynamic petData;
  const Random_Image_Card({required this.petData, Key? key}) : super(key: key);

  @override
  State<Random_Image_Card> createState() => _Random_Image_CardState();
}

class _Random_Image_CardState extends State<Random_Image_Card> {
  List<dynamic> photoURL = [];
  int? selectedImage;

  @override
  void initState() {
    super.initState();
    photoURL = widget.petData['photoUrls'] ?? [];
    if (photoURL.isNotEmpty) {
      selectedImage = random.nextInt(photoURL.length);
    }
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 180,
      width: 180,
      child: Card(
        child: Container(
          decoration: photoURL.isNotEmpty && selectedImage != null
              ? BoxDecoration(
                  image: DecorationImage(
                    alignment: Alignment.center,
                    image: image(photoURL[selectedImage!]).image,
                    fit: BoxFit.scaleDown,
                  ),
                )
              : const BoxDecoration(
                  image: DecorationImage(
                    alignment: Alignment.center,
                    image: NetworkImage("https://cdn-cziplee-estore.azureedge.net//cache/no_image_uploaded-253x190.png"),
                    fit: BoxFit.scaleDown,
                  ),
                ),
        ),
      ),
    );
  }
}

关键修改说明

  • 主页面维护allPetData列表,滚动到底部时加载新数据并累加,实现真正的无限滚动
  • 每个GridView项在itemBuilder中生成独立随机宠物索引,确保卡片内容不重复
  • 卡片组件直接接收单条宠物数据,独立处理图片随机选择,摆脱对外部单一随机值的依赖
  • 增加加载状态管理,避免重复发起API请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 03:24:23