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

如何解决ListView中‘type 'int' is not a subtype of type 'String'’错误?

Flutter ListView 报 'type 'int' is not a subtype of type 'String'' 错误

问题描述

我用以下代码从Firebase获取数据填充menuItemList,用于ListView展示:

Future<void> allMenuDetail(String orderID) async {
  _streamSubscriber =
      _dbRef.child('MenuItem/$orderID').onValue.listen((event) {
    if (event.snapshot.value != null) {
      var data = event.snapshot.value as Map;

      var price = data['price'];
      var itemName = data['itemName'];
      var desc = data['description'];
      var itemImg = data['img'];
      //  String itemID = data['id'];

      Map<String, dynamic> myMap = {
        'price': price,
        'itemName': itemName,
        'desc': desc,
        'img': itemImg,
        'itemID': itemID
      };
      List<dynamic> shortList = [myMap];
      menuItemList.addAll(shortList);
      setState(() {});
    } else {
    }
  });
}

但在ListView部分出现type 'int' is not a subtype of type 'String'错误,错误指向标注行,ListView代码如下:

Expanded(
    child: ListView.builder(
  itemCount: menuItemList.length,
  itemBuilder: (context, index) {
    final item = menuItemList[index];//Error shows up here
    String price = item['price'];
    String itemName = item['itemName'];
    String desc = item['description'];
    String itemImg = item['img'];
    String itemID = item['itemID'];

    print('!');

    //   var cartPorducts = item['cartProducts'];
    return Container(
        height: 95,
        decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(24)),
        margin: const EdgeInsets.fromLTRB(8, 10, 8, 10),
        child: InkWell(
            onTap: () {
              Navigator.of(context).push(MaterialPageRoute(
                  builder: (context) => ItemPageState(
                      path: categoryPath,
                      itemName: itemName,
                      desc: desc,
                      price: 9,
                      itemImg: itemImg,
                      id: itemID)));
              // }
            },
            child: Card(
              margin: const EdgeInsets.fromLTRB(8, 10, 8, 10),
              color: Colors.white,
              clipBehavior: Clip.antiAlias,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(24),
              ),
              child: Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    ClipRect(
                        child: Align(
                      alignment: Alignment.center,
                      widthFactor: 0.8,
                      child: Image(
                        image: AssetImage(itemImg),
                        height: 100,
                        width: 150,
                        fit: BoxFit.cover,
                      ),
                    )),
                    const SizedBox(width: 30),
                    Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          itemName,
                          style: const TextStyle(
                              color: Colors.black, fontSize: 25),
                        ),
                        Text(
                          'Price: R', //+ price.toString(),
                          style: const TextStyle(
                              color: Colors.black, fontSize: 18),
                        ),
                      ],
                    ),
                    const SizedBox(width: 30),
                  ]),
            )));
  },
))

其他地方用相同方式实现正常,请问问题出在哪里?


问题原因及解决方案

核心问题:类型不匹配

错误提示type 'int' is not a subtype of type 'String',本质是你把int类型的值强制赋值给String类型变量,主要有两个关键点:

  1. price的类型冲突
    从Firebase读取的price大概率是整数类型(数据库中存的是数字),但你在ListView里直接写String price = item['price'];,试图将int直接转为String,触发类型转换错误。

  2. itemID未正确初始化
    你注释掉了String itemID = data['id'];,但在myMap里仍引用itemID,导致该变量未定义,后续赋值给String itemID也会引发潜在问题。

具体修改步骤

  • 处理price类型转换:将String price = item['price'];改为安全的类型转换:

    // 方式1:直接转String
    String price = item['price'].toString();
    // 方式2:先存为int再按需转换
    int priceInt = item['price'];
    String price = priceInt.toString();
    
  • 修复itemID的赋值:取消注释String itemID = data['id'];,确保从数据库正确读取itemID:

    String itemID = data['id']; // 取消这行的注释
    
  • 其他字段的安全校验:如果itemName、desc等字段在数据库中可能不是String类型,建议添加空安全转换:

    String itemName = item['itemName']?.toString() ?? '';
    String desc = item['description']?.toString() ?? '';
    

额外优化建议

建议创建MenuItem实体类,用类型化方式存储数据,彻底避免动态类型带来的错误:

class MenuItem {
  final int price;
  final String itemName;
  final String desc;
  final String img;
  final String itemID;

  MenuItem({
    required this.price,
    required this.itemName,
    required this.desc,
    required this.img,
    required this.itemID,
  });

  factory MenuItem.fromMap(Map<String, dynamic> map) {
    return MenuItem(
      price: map['price'] as int,
      itemName: map['itemName'] as String,
      desc: map['description'] as String,
      img: map['img'] as String,
      itemID: map['id'] as String,
    );
  }
}

获取数据时转换为实体类:

MenuItem menuItem = MenuItem.fromMap(data);
menuItemList.add(menuItem);

之后在ListView里直接调用类型化属性,无需再做类型转换。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 04:35:40