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

Flutter RangeError(index)问题:API数据正常却无法展示

解决Flutter中RangeError(index)列表展示错误

从API获取数据并存储到模型后,使用ProductCardList组件通过GridView.builder展示数据时,出现范围错误:RangeError (index): Invalid value: Only valid value is 0: -1,数据已正确接收但无法正常渲染。

错误原因

  1. 索引越界未校验:ProductCardList组件直接通过widget.dataModel[widget.index]访问数据,未对数据列表的有效性、索引的合法性做判断,当索引为-1(如数据加载过程中的临时状态)或列表长度不足时触发错误。
  2. 控制器重复实例化:在build方法中使用Get.put(HomeScreenController())会重复创建控制器实例,可能导致状态异常。
  3. 空数据场景未处理:父组件未判断产品列表是否为空,GridView.builder在空列表时仍可能尝试构建item。

解决方案

方案1:添加数据有效性校验(快速修复)

在ProductCardList的build方法开头增加校验,非法状态返回占位Widget:

@override
Widget build(BuildContext context) {
  // 新增:校验数据和索引合法性
  if (widget.dataModel == null || widget.dataModel.isEmpty || widget.index < 0 || widget.index >= widget.dataModel.length) {
    return const SizedBox.shrink(); // 或自定义加载/空占位UI
  }
  
  // 替换Get.put为Get.find,避免重复创建控制器
  final homeController = Get.find<HomeScreenController>();
  // ... 原有组件代码
}

方案2:优化父组件空数据处理

在GridView.builder外层判断列表是否为空,展示对应空状态:

Expanded(
  child: (campaignDetailsModel?.data?.products?.isEmpty ?? true)
      ? Center(child: Text("暂无产品")) // 自定义空状态UI
      : GridView.builder(
          padding: EdgeInsets.symmetric(horizontal: isMobile(context)? 15.w:10.w, vertical: 8.h),
          itemCount: campaignDetailsModel!.data!.products!.length,
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: isMobile(context)? 2:3,
            childAspectRatio: .75,
            mainAxisSpacing: isMobile(context)? 15:20,
            crossAxisSpacing: isMobile(context)? 15:20,
          ),
          itemBuilder: (context, index) {
            return ProductCardList(
              dataModel: campaignDetailsModel!.data!.products!,
              index: index,
            );
          },
        ),
),

方案3:重构组件(更优雅的写法)

将ProductCardList改为接收单个产品模型,彻底避免索引操作:

// 修改ProductCardList参数
class ProductCardList extends StatefulWidget {
  const ProductCardList({
    Key? key,
    required this.product, // 改为单个产品模型
  }) : super(key: key);
  final dynamic product;

  @override
  State<ProductCardList> createState() => _ProductCardListState();
}

// 组件内部直接访问widget.product
class _ProductCardListState extends State<ProductCardList> {
  final currencyConverterController = Get.find<CurrencyConverterController>();

  @override
  Widget build(BuildContext context) {
    final homeController = Get.find<HomeScreenController>();
    return Ribbon(
      farLength: widget.product.isNew!
          ? isMobile(context) ? 20 : 30
          : 1,
      nearLength: widget.product.isNew!
          ? isMobile(context) ? 40 : 50
          : 1,
      title: widget.product.isNew! ? AppTags.neW.tr : "",
      // ... 所有原widget.dataModel[widget.index]替换为widget.product
    );
  }
}

// 父组件调用时传入单个产品
itemBuilder: (context, index) {
  final product = campaignDetailsModel!.data!.products![index];
  return ProductCardList(product: product);
},

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 10:10:40