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

Flutter sqflite列表加载3条数据后返回页面崩溃问题

解决Sqflite列表数据≥3条时返回页面崩溃的问题

常见触发原因及对应解决方案

1. FutureBuilder的Future重复创建导致状态混乱

如果在build方法里直接调用数据库查询方法(比如_db.getStats()),每次页面重建都会生成新的Future。当从添加页面返回时,旧的Future可能还在执行,新的Future又开始,导致ListView拿到不一致的数据,触发Sliver断言错误。

解决办法:把Future存到State变量中,在initState里初始化:

late Future<List<BodyStats>> _statsFuture;

@override
void initState() {
  super.initState();
  _statsFuture = _databaseHelper.fetchBodyStats();
}

// 后续在FutureBuilder中使用这个预初始化的Future
FutureBuilder<List<BodyStats>>(
  future: _statsFuture,
  builder: (context, snapshot) {
    // 构建UI逻辑
  },
)

2. ListView的itemCount与实际数据长度不匹配

当数据数量变化时,如果itemCount没有和snapshot.data的长度严格对应,或者错误/加载状态下返回了多个子项,就会触发Sliver的断言错误。

检查&修复点:

  • 仅在snapshot.hasData时渲染ListView,且itemCount设为snapshot.data!.length
  • 加载/错误/空数据状态下,返回单个中心Widget(而非ListView子项)

示例代码:

builder: (context, snapshot) {
  if (snapshot.connectionState == ConnectionState.waiting) {
    return const Center(child: CircularProgressIndicator());
  } else if (snapshot.hasError) {
    return Center(child: Text('加载失败: ${snapshot.error}'));
  } else if (!snapshot.hasData || snapshot.data!.isEmpty) {
    return const Center(child: Text('暂无数据'));
  }
  
  // 数据正常时渲染列表
  return ListView.builder(
    itemCount: snapshot.data!.length,
    itemBuilder: (context, index) {
      final stat = snapshot.data![index];
      return ListTile(
        title: Text('体重: ${stat.weight}kg'),
        subtitle: Text(stat.date.toString()),
      );
    },
  );
}

3. 从添加页面返回后未刷新数据

如果添加新数据后,没有重新获取数据库数据,FutureBuilder会继续使用旧的Future,导致内存中的数据和实际数据库数据不一致,触发断言。

解决办法:利用Navigator.push的返回值触发数据刷新:

// 在BodyStatsListScreen中跳转添加页面
final updateTrigger = await Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => AddBodyStatsScreen()),
);

// 若添加页面返回标记,重新获取数据
if (updateTrigger == true) {
  setState(() {
    _statsFuture = _databaseHelper.fetchBodyStats();
  });
}

// 在AddBodyStatsScreen中完成添加后返回标记
Navigator.pop(context, true);

4. 数据模型转换存在空值/类型错误

如果从数据库读取的数据未正确转换为模型(比如null值未处理、类型不匹配),构建列表项时会抛出异常,间接触发Sliver断言。

检查点:

  • 确保模型的fromMap方法处理所有字段,避免null或类型转换错误
  • 比如处理数值类型时,用(map['weight'] as num).toDouble()而非直接强转

示例模型转换:

class BodyStats {
  final int id;
  final double weight;
  final DateTime recordDate;

  BodyStats({required this.id, required this.weight, required this.recordDate});

  factory BodyStats.fromMap(Map<String, dynamic> map) {
    return BodyStats(
      id: map['id'] as int,
      weight: (map['weight'] as num).toDouble(),
      recordDate: DateTime.parse(map['record_date'] as String),
    );
  }
}

排查步骤总结

  1. 确认FutureBuilder的Future是在initState初始化,而非build方法内
  2. 检查ListView的itemCount是否与数据长度严格一致,异常状态返回单个Widget
  3. 从添加页面返回时,手动触发数据刷新
  4. 验证数据模型的转换逻辑,确保无空值或类型错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:15:44