Flutter中插入SQLite数据后FutureBuilder无法更新的问题
解决Flutter FutureBuilder列表插入数据后不更新的问题
问题根源
你的代码存在两个核心问题:
- 在
build方法中每次初始化futureData = getAllGoals(),虽然build调用时会重新获取数据,但从Widget3返回时,Goals页面的build不一定会自动触发。 - 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
相关产品推荐
相关产品推荐

