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

Flutter使用sqflite时Future<List<Item>>无length属性报错解决方案咨询

错误原因

你遇到的两个报错分别由以下原因导致:

  1. The getter 'length' isn't defined for the class 'Object':使用FutureBuilder时未指定泛型,Dart无法推断snapshot.data的类型,默认识别为通用Object类,自然不存在length属性。
  2. A non-null value must be returned since the return type 'Widget' doesn't allow null:FutureBuilder的builder方法要求所有逻辑分支都必须返回非空Widget,你之前的代码没有覆盖加载中、加载失败、无数据等分支,存在返回null的情况,违反空安全规则。

解决方案

方案1:直接修正FutureBuilder写法

给FutureBuilder明确指定List<Item>泛型,同时覆盖所有状态分支返回对应Widget:

// 先在页面内初始化ItemsController
final ItemsController itemsController = Get.put(ItemsController());

@override
Widget build(BuildContext context) {
  return FutureBuilder<List<Item>>(
    // 注意不要直接把loadAllItems写在这,避免每次组件重建重复请求,实际使用可提前存在变量中
    future: itemsController.loadAllItems(),
    builder: (context, snapshot) {
      // 加载中状态
      if (snapshot.connectionState == ConnectionState.waiting) {
        return const Center(child: CircularProgressIndicator());
      }
      // 加载失败状态
      if (snapshot.hasError) {
        return Center(child: Text('加载失败:${snapshot.error}'));
      }
      // 无数据状态
      if (!snapshot.hasData || snapshot.data!.isEmpty) {
        return const Center(child: Text('暂无待办事项'));
      }
      // 有数据时返回列表
      final itemList = snapshot.data!;
      return ListView.builder(
        itemCount: itemList.length,
        itemBuilder: (context, index) {
          final currentItem = itemList[index];
          // 替换为你自己的列表项组件
          return ListTile(
            title: Text(currentItem.name ?? '未命名待办'),
            subtitle: Text(currentItem.notes ?? '无备注'),
          );
        },
      );
    },
  );
}

方案2:适配GetX的响应式方案(更推荐)

既然你已经用了GetX作为状态管理,可直接将列表转为响应式变量,避免反复写FutureBuilder:

  1. 先修改ItemsController:
class ItemsController extends GetxController {
  // 原有代码保持不变
  // 新增响应式待办列表
  final RxList<Item> items = <Item>[].obs;

  // 新增拉取数据并更新列表的方法
  Future<void> fetchAllItems() async {
    final dbController = DBController();
    final List<Map<String, dynamic>> itemsMaps =
        await dbController.query(tableItems);
    items.value = List.generate(itemsMaps.length, (i) => Item.fromMap(itemsMaps[i]));
  }

  // 修改addItem方法,新增数据后自动刷新列表
  Future<int> addItem(Item item) async {
    final dbController = DBController();
    int id = await dbController.insertElement(tableItems, item);
    await fetchAllItems();
    return id;
  }

  // 后续update、delete方法实现后也调用fetchAllItems即可自动刷新列表
}
  1. 页面中直接用Obx监听列表变化构建视图:
final ItemsController itemsController = Get.put(ItemsController());

@override
void initState() {
  super.initState();
  // 页面初始化时拉取一次数据
  itemsController.fetchAllItems();
}

@override
Widget build(BuildContext context) {
  return Obx(() {
    if (itemsController.items.isEmpty) {
      return const Center(child: Text('暂无待办事项'));
    }
    return ListView.builder(
      itemCount: itemsController.items.length,
      itemBuilder: (context, index) {
        final currentItem = itemsController.items[index];
        return ListTile(
          title: Text(currentItem.name ?? '未命名待办'),
          subtitle: Text(currentItem.notes ?? '无备注'),
        );
      },
    );
  });
}

额外优化建议

修改Item类的fromMap方法参数类型,避免隐式类型转换警告:

// 把原方法的Map改为Map<String, dynamic>
Item.fromMap(Map<String, dynamic> map) {
  this._id = map[colId];
  this._name = map[colName];
  this._notes = map[colNotes];
  this._expiryDate = map[colExpiryDate];
  this._category = map[colCategory];
  this._quantity = map[colQuantity];
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 02:09:02