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

Flutter页面启动时FutureBuilder无数据,热重载后恢复的问题排查

问题分析与解决方案

核心问题推测

首次打开页面时_db大概率还没完成初始化,导致fetchARoad直接返回空列表;热重载时数据库已经初始化完毕,所以能正常获取数据。另外,直接在FutureBuilder的future参数里调用异步方法,会触发每次组件build都重新执行请求,进一步放大时序问题。

解决方案1:固定Future实例,避免重复执行

把Future实例存为State的成员变量,在initState里初始化,确保只执行一次:

late final Future<List<Road>> _roadFuture;

@override
void initState() {
  super.initState();
  // 仅在页面初始化时执行一次查询
  _roadFuture = _roadStorage.fetchARoad(widget.currentClientId.toInt());
}

// FutureBuilder使用这个预初始化的实例
FutureBuilder<List<Road>>(
  future: _roadFuture,
  builder: (context, snapshot) {
    // ... 原builder逻辑
  },
)

解决方案2:确保数据库初始化完成再查数据

检查你的数据库初始化逻辑,保证_db在调用fetchARoad前已经准备好。可以给数据库类加个初始化方法,等它完成后再执行查询:

// 数据库类中新增初始化方法
Future<void> initDatabase() async {
  _db = await openDatabase(
    // 你的数据库路径、版本、创建表逻辑等
  );
}

// 页面中等待数据库初始化后再发起查询
@override
void initState() {
  super.initState();
  _loadRoadData();
}

void _loadRoadData() async {
  await _roadStorage.initDatabase();
  setState(() {
    _roadFuture = _roadStorage.fetchARoad(widget.currentClientId.toInt());
  });
}

额外排查点

  1. 检查Road.fromRow方法的字段映射是否正确,比如数据库返回的字段名大小写、拼写是否和实体类属性匹配(Sqflite返回的字段名默认是小写,注意和你的Road类属性对应)。
  2. 在fetchARoad里加日志,确认首次调用时的状态:
Future<List<Road>> fetchARoad(int ClientID) async {
  final db = _db;
  print('DB实例状态: ${db == null ? "未初始化" : "已就绪"}');
  if (db == null) return [];
  var read = await db.query('ROAD', ...);
  print('查询结果条数: ${read.length}');
  List<Road> roadlist = read.isNotEmpty ? read.map((e) => Road.fromRow(e)).toList() : [];
  return roadlist;
}
  1. 确认widget.currentClientId.toInt()在首次打开时是否为有效ID,会不会是默认值(比如0)导致查询不到数据,热重载时才拿到正确值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 23:25:54