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

Flutter中插入SQLite数据后FutureBuilder无法更新的问题

解决Flutter FutureBuilder列表插入数据后不更新的问题

问题根源

你的代码存在两个核心问题:

  1. 在build方法中每次初始化futureData = getAllGoals(),虽然build调用时会重新获取数据,但从Widget3返回时,Goals页面的build不一定会自动触发。
  2. FutureBuilder的future一旦完成,除非重新赋值新的Future实例,否则不会重新执行异步请求,导致无法获取新插入的数据。

解决方案一:修复FutureBuilder用法,手动触发刷新

步骤1:重构Goals组件的状态管理

将futureData的初始化移到initState,并添加刷新方法触发重新获取数据:

class Goals extends StatefulWidget {
  const Goals({Key? key}) : super(key: key);

  @override
  State<Goals> createState() => _GoalsState();
}

class _GoalsState extends State<Goals> {
  late Future<List<Goal>> futureData;

  @override
  void initState() {
    super.initState();
    // 初始化时首次获取数据
    futureData = getAllGoals();
  }

  // 刷新数据的方法
  void _refreshGoals() {
    setState(() {
      // 赋值新的Future实例,触发FutureBuilder重新执行
      futureData = getAllGoals();
    });
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<Goal>>(
      future: futureData,
      builder: (BuildContext context, AsyncSnapshot<List<Goal>> snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Center(child: CircularProgressIndicator());
        } else if (snapshot.hasError) {
          return Text('加载失败: ${snapshot.error}');
        } else if (snapshot.hasData) {
          final goals = snapshot.data!;
          if (goals.isEmpty) {
            return const Center(
              child: Text(
                "No Goals added yet",
                style: TextStyle(
                  fontSize: 20.0,
                  fontWeight: FontWeight.bold,
                  fontFamily: "JosefinSans",
                ),
              ),
            );
          }
          return Scaffold(
            body: Padding(
              padding: const EdgeInsets.all(16.0),
              child: SingleChildScrollView(
                child: // 你的UI代码
              ),
            ),
          );
        } else {
          return const Text("No Goals added yet");
        }
      },
    );
  }
}

步骤2:从Widget3返回后触发刷新

在首页的悬浮按钮点击事件中,等待Widget3关闭后,调用Goals组件的刷新方法。可以通过GlobalKey获取Goals的状态:

// 在首页的State中定义GlobalKey
final GlobalKey<_GoalsState> goalsKey = GlobalKey<_GoalsState>();

// 底部导航的第一个Tab使用该Key
TabBarView(
  children: [
    Goals(key: goalsKey),
    // 其他Tab页面
  ],
)

// 悬浮按钮的点击事件
FloatingActionButton(
  onPressed: () async {
    // 打开Widget3并等待返回
    await Navigator.push(context, MaterialPageRoute(builder: (context) => Widget3()));
    // 调用Goals的刷新方法
    goalsKey.currentState?._refreshGoals();
  },
  child: const Icon(Icons.add),
)

解决方案二:改用StreamBuilder自动监听数据库变化

如果你的SQLite库支持流监听(比如sqflite的rawQueryStream),可以使用StreamBuilder自动获取数据库更新,无需手动触发刷新:

步骤1:实现数据库流查询方法

Stream<List<Goal>> getAllGoalsStream() {
  // 假设db是你的SQLite数据库实例
  return db.rawQueryStream('SELECT * FROM goals').map((rows) {
    return rows.map((row) => Goal.fromMap(row)).toList();
  });
}

步骤2:重构Goals组件使用StreamBuilder

class _GoalsState extends State<Goals> {
  late Stream<List<Goal>> goalsStream;

  @override
  void initState() {
    super.initState();
    goalsStream = getAllGoalsStream();
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<List<Goal>>(
      stream: goalsStream,
      builder: (BuildContext context, AsyncSnapshot<List<Goal>> snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Center(child: CircularProgressIndicator());
        } else if (snapshot.hasError) {
          return Text('加载失败: ${snapshot.error}');
        } else if (snapshot.hasData) {
          final goals = snapshot.data!;
          if (goals.isEmpty) {
            return const Center(
              child: Text(
                "No Goals added yet",
                style: TextStyle(
                  fontSize: 20.0,
                  fontWeight: FontWeight.bold,
                  fontFamily: "JosefinSans",
                ),
              ),
            );
          }
          return Scaffold(
            body: Padding(
              padding: const EdgeInsets.all(16.0),
              child: SingleChildScrollView(
                child: // 你的UI代码
              ),
            ),
          );
        } else {
          return const Text("No Goals added yet");
        }
      },
    );
  }
}

这种方式下,当你在Widget3插入数据到SQLite后,流会自动推送新的列表数据,StreamBuilder会自动更新UI。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 16:05:34