如何在Widget构建前将sqflite数据预加载到变量中?
解决方案
核心修改逻辑
- 新增加载状态标记规避空值报错:在State类中添加
_isDataLoaded布尔变量标记数据加载状态,build阶段优先判断状态,未加载完成时展示占位内容,不会直接访问null的data变量触发异常。 - 数据加载完成后主动触发UI更新:异步方法
loadData拿到数据库返回结果后调用setState,仅触发一次页面重建更新UI,后续动画导致的页面重建不会重新走数据库读取逻辑,也不会出现加载进度条。 - 动画重建优化:可以将执行进度条动画的模块拆分为独立的StatefulWidget,动画状态更新仅触发自身重建,不会带动整个父页面重绘,进一步减少不必要的性能消耗。
修改后可运行代码
import 'package:flutter/material.dart'; import 'package:phonica/sql/service.dart'; class Testing extends StatefulWidget { const Testing({Key? key}) : super(key: key); @override State<Testing> createState() => _TestingState(); } class _TestingState extends State<Testing> with TickerProviderStateMixin { final _databaseService = DatabaseService(); var data; // 新增加载状态标记 bool _isDataLoaded = false; @override void initState() { super.initState(); loadData(); } loadData() async { var cramModel = await _databaseService.readDatabaseTable(); // 加载完成后调用setState更新状态 setState(() { data = cramModel[1]; _isDataLoaded = true; }); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.indigo[50], body: Container( child: LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Center( // 加载完成前展示占位文本,也可以放空的Container child: _isDataLoaded ? Text( data["WORD_EN"], ) : const Text("加载中..."), ), ], ); }, ), ), ); } }
可选:FutureBuilder正确用法(避免重复显示加载动画)
如果你后续还是想使用FutureBuilder,只要把Future对象提前存在State中,不要在build方法里直接生成新的Future即可,已完成的Future不会重新触发加载逻辑:
// 仅展示修改部分代码 class _TestingState extends State<Testing> with TickerProviderStateMixin { final _databaseService = DatabaseService(); late Future _dataFuture; // 提前声明Future变量 @override void initState() { super.initState(); _dataFuture = loadData(); // initState中仅初始化一次Future } loadData() async { var cramModel = await _databaseService.readDatabaseTable(); return cramModel[1]; } @override Widget build(BuildContext context) { return FutureBuilder( future: _dataFuture, // 复用同一个Future对象,不会重复加载 builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { return Text(snapshot.data["WORD_EN"]); } return const Text("加载中..."); } ); } }
内容的提问来源于stack exchange,提问作者Ian Rajkumar
相关产品推荐
相关产品推荐

